GFX Related Questions

Strictly for discussing ZSNES development and for submitting code. You can also join us on IRC at irc.libera.chat in #zsnes.
Please, no requests here.

Moderator: ZSNES Mods

smkdan
Hazed
Posts: 88
Joined: Sun Dec 19, 2004 4:55 am

GFX Related Questions

Post by smkdan »

So I've been trying to learn the SNES hardware and i've got a few things down (The essentials for 65186 ASM and simple joypad reading) but im a bit lost with trying to the simple task of uploading tiles to vram and displaying them.

I dont really have any prior knowledge of programming so the tech docs really baffle me.

So, could anyone point me to a tutorial that walks you through the process of writing a tile to vram and having it displayed? I got the whole bitplane tiledata format and the palettes from CGRAM down but thats all I understand from the docs. It helps alot to see examples and a nicely detailed explanation rather than tech docs that that dont really go into detail.

Can anyone help a noob out?

Thanks,

edit: gave it a more fitting title
Last edited by smkdan on Thu Apr 20, 2006 1:54 pm, edited 1 time in total.
neviksti
Lurker
Posts: 122
Joined: Thu Jul 29, 2004 6:15 am

Post by neviksti »

I wouldn't really call it a tutorial, but considering it sounds like you are self motivated and just need some examples, try the SNES starter kit that I threw together a couple years ago. You can get it here:
http://nesdev.parodius.com/
(just search for "starter")

It has example code to get most people started and tools for graphics conversion.
Nightcrawler
Romhacking God
Posts: 922
Joined: Wed Jul 28, 2004 11:27 pm
Contact:

Post by Nightcrawler »

We've some useful things for you on ROMhacking.net. This document will probably help.

ROMhacking.net Doc

Aside from that, if you know assembly, understand graphics, all you should need is a good register document and just go to town and experiment.

The process is pretty simple. After initialization, just set your VRAM BG tilemap address then the tile data address for that background. Then just transfer the data and tilemap to those locations using the write to VRAM registers. And remember, despite inaccurate ZSNES letting you, you can ONLY write to VRAM on the real SNES either during Vblank or forced blank(you manually turn the screen off).

You should probably use BSNES, Super Slueth or SNEeSe for testing. They are the only emulators that properly emulate this portion of the system.
[url=http://transcorp.romhacking.net]TransCorp[/url] - Home of the Dual Orb 2, Cho Mahou Tairyku Wozz, and Emerald Dragon SFC/SNES translations.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
smkdan
Hazed
Posts: 88
Joined: Sun Dec 19, 2004 4:55 am

Post by smkdan »

Thanks for the replies, but I have another question to ask.

I thought I had a solid understand on DMA...It seemed pretty straightforward. I decide to try it out and I just cant get it to work at all. I'd like to get it working for me before I even start with tiles and other stuff.

Code: Select all

.INCLUDE "header.inc"
.INCLUDE "initsnes.asm"

.BANK 0 SLOT 0
.ORG 0
.SECTION "Main"

Start:
InitSNES	;Initizlise all those registers :S - I might dig through it sometime
stz $2121	;modify colour 0
bra DMA				

DMA:  
stz $4300	;set the mode
lda #$22	;set destination
sta $4301	
ldx #palette	;set source
stx $4302	
lda #:palette	;set bank
sta $4304	
ldx $#0002     ;set size to 2 bytes
stx $4305	
lda #$01	;start transfer
sta $420B	

bra TurnOnScreen; 

TurnOnScreen:
lda #$0F	;turn on screen
sta $2100	

Loop:
bra Loop	;is this even needed?

.ENDS

.BANK 1 
.ORG 0
.SECTION "Palettestuff"

palette:
.db $FF, $FF

.ENDS
Using WLA here

Simply want to switch the screen colour via DMA but im not having much luck at all. It seems so simple so chances are im missing something blatantly obvious, but what?

Thanks,
Nightcrawler
Romhacking God
Posts: 922
Joined: Wed Jul 28, 2004 11:27 pm
Contact:

Post by Nightcrawler »

Ok, I think there a few things missing here. I'm a little rusty as I haven't done any SNES programming in several months, so bear with me.

To start, let's run by 3 points.

1.) You can just write directly to the $2122 register. You don't have to use DMA, however if you're using DMA simply to learn how to use it, then disregard that.

2.) It looks like your DMA is set up correctly.

3.) Are you sure the screen is turned off to begin with? I'd check that in your initialization. Don't assume anything.

Ok, now we get into what I think it probably the real problem here. Ok, so you set the first color in the palette. Let's say that went successfully(CHECK THAT IT DID in a debugger or savestate viewer such as VSNES!). If you know that's correct then...

SO WHAT? What is that going to do? It does NOTHING. (not being offensive or yelling here, just emphasising the logic you'll need to take with the systems such the SNES that don't do ANYTHING unless you tell them to.)

Why would your screen USE that color? Color 0 doesn't automatically become the screen background color. What is ON your screen? NOTHING is. You haven't even set a screen mode or enabled any backgrounds.

1.) Set the background mode you are going to use via $2105

2.) You will probably need to set the tiledata and tilemap locations in VRAM. I dont' think you can set a background color without using any tiles, but I may be wrong here.

3.) You'll need to actually stick the tiledata and tilemap in VRAM or else the screen will pobably have garbage on it on the real SNES at least.

4.) Now, if you have your background set up correct and all the data is in place, ENABLE the background BEFORE turning on the screen.

By the time you've gotten that far, you should see SOMETHING on the screen. ;)

That should point you in the right direction I think. You really weren't very descriptive on what you already tried to do, what you verified works, or what your problem actually IS.

Remember that you can verify via debugger and savestates what is happening in your code. Make sure the portions of your code work so you can eliminate them as the problem. You can check hardware states via a savesate using a savestate viewer such as VSNES.
[url=http://transcorp.romhacking.net]TransCorp[/url] - Home of the Dual Orb 2, Cho Mahou Tairyku Wozz, and Emerald Dragon SFC/SNES translations.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
smkdan
Hazed
Posts: 88
Joined: Sun Dec 19, 2004 4:55 am

Post by smkdan »

I guess I could've been a bit clearler in my post.

Yes, Im doing this to learn to use DMA. The task can easily be done without DMA but I'd like to have something simple to work with. I had a look at initsnes and it does turn off the screen (Doesnt turn it back on during the routine) somewhere in it.

Im quite sure the code does indeed do something. The task is to switch the screen to white. If it does show a white screen, then I know the DMA was successful. If I just get black, then something is wrong ofcourse.

Code: Select all

.INCLUDE "header.inc"
.INCLUDE "initsnes.asm"

.BANK 0 SLOT 0
.ORG 0
.SECTION "Code"

Start:

InitSNES	;Nevitski's handy macro, though I hope I wont be needing it for long.            
stz $2121       ;Colour 0
lda #$FF	;byte one of white		      
sta $2122           
lda #$FF      	;byte two of white
sta $2122          
lda #$0F 	;switch on screen     
sta $2100   
bra loop	;obligatory loop

loop:
bra loop	;eh

.ENDS       
The simple, non-DMA code that switches the screen colour to white (I know the first bit of the colour data does nothing but no harm done right?). Didnt have to set any BG modes, upload any tilemaps etc. Are you absolutely sure it doesnt work like this? Perhaps initsnes is doing something of the sort but I cant find anything that would automatically do something like this, or is it just the rustiness? :P

I'll look into a debugger tomorrow when I have some time. Thanks for the help so far.

EDIT:Well, nothing is being written to CGRAM at all...Theres something im totally missing about DMA :( . A is 8bit, X and Y are 16bit and the screen is off at the start...I really cant think of anything thats causing this.
Nightcrawler
Romhacking God
Posts: 922
Joined: Wed Jul 28, 2004 11:27 pm
Contact:

Post by Nightcrawler »

Ok, I brushed up my skills again and am now all information coming from me is 100% accurate.

In fact, I even did this little coding excersise to confirm.

The DMA code AND the non DMA code will NOT work unless a BG is enabled. Since your non DMA code worked, I have to assume InitSNES sets $212c. Does it? What does it initialize this register with?

You really should stop relying on pre made initializations and start to learn how to initialize what you need yourself. You're not really going to understand it without donig this. You do NOT need to initialize the entire system like some files will lead you to believe. You only need to initialize what you're using and things that directly effect the display of an image on screen. This is actually very little.

Anyway, this is just for your knowledge. This isn't why your code doesn't work.

Your actual DMA code is CORRECT. I assume your source address loads correctly(VSNES can confirm this)? I use xkas and don't use that syntax.

The only thing I do differently is STOP DMA transfers BEFORE I load it up. You may be loading data into an active channel. So disable that channel beore loading up those registers and then enable it at the end as you did. When it comes to hacking games, this is unbelievably important. Usually you will wait for a channel to be free and inactive and then set it up, wait for vblank, and fire it off.

In our simple case here though, all you need to do is:

stz $420b before your DMA code.

"bra Loop ;is this even needed?" You bet your ass it is. Otherwise, program execution continues into unknown instructions. There is no such thing as an 'end' program in assembly. The PC counter keeps incrementing. This loop will halt your program at the end of your code there.

Other than what I've told you, nothing else is is wrong with your code. Mine works just fine. The only differences are the assembler and the initializations, so if you still have a problem, it's with one of those. I have no idea what your initialization file is actually doing because I can't see it.
[url=http://transcorp.romhacking.net]TransCorp[/url] - Home of the Dual Orb 2, Cho Mahou Tairyku Wozz, and Emerald Dragon SFC/SNES translations.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
byuu

Post by byuu »

The only thing I do differently is STOP DMA transfers BEFORE I load it up. You may be loading data into an active channel. So disable that channel beore loading up those registers and then enable it at the end as you did. When it comes to hacking games, this is unbelievably important. Usually you will wait for a channel to be free and inactive and then set it up, wait for vblank, and fire it off.
I've explained this to you before. stz $420b does absolutely nothing. When you enable a DMA channel, it starts transferring one opcode cycle later. It transfers all data, no matter how much there is, regardless if vblank is enabled or not, all at once, and CPU execution does not resume until all eight channels are clear.
stz $420c would clear HDMA. I'm not sure what would happen if you enabled DMA while HDMA was active. I imagine the DMA would disable the HDMA channel, though.
smkdan
Hazed
Posts: 88
Joined: Sun Dec 19, 2004 4:55 am

Post by smkdan »

Here is nevitski's initsnes so you can see what it's doing. It is quite long and Im sure I dont need all of it but until I get this issue fixed up I'll hold off making my own intializing code.

Code: Select all

.MACRO InitSNES
  sei                     ;disable interrupts
  clc                     ;switch to native mode
  xce

  REP #$38		; mem/A = 16 bit, X/Y = 16 bit
			;decimal mode off

  LDX #$1FFF	;Setup the stack
  TXS			;Transfer Index X to Stack Pointer Register

  ;do the rest of the initialization in a routine
  JSL $008000

  SEP #$20		; mem/A = 8 bit
.ENDM

;----------------------------------------------------------------------------

.BANK 0 SLOT 0
.ORG 0
.SECTION "InitializeSNESCode" FORCE

InitializeSNES:
  PHK			;set Data Bank = Program Bank
  PLB

  LDA #$0000	;set Direct Page = $0000
  TCD			;Transfer Accumulator to Direct Register

  LDX $1FFD		;we clear all the mem at one point ...
  STX $4372  	;so save the return address in a place that won't get overwritten
  LDX $1FFF
  STX $4374

  SEP #$20		; mem/A = 8 bit
  REP #$10

  LDA #$8F
  STA $2100		;turn screen off for now, set brightness to normal

  LDX #$2101
_Loop00:		;regs $2101-$210C
  STZ $00,X		;set Sprite,Character,Tile sizes to lowest, and set addresses to $0000
  INX
  CPX #$210D
  BNE _Loop00

_Loop01:		;regs $210D-$2114
  STZ $00,X		;Set all BG scroll values to $0000
  STZ $00,X
  INX
  CPX #$2115
  BNE _Loop01

  LDA #$80		;reg $2115
  STA $2115		; Initialize VRAM transfer mode to word-access, increment by 1

  STZ $2116		;regs $2117-$2117
  STZ $2117		;VRAM address = $0000

			;reg $2118-$2119
			;VRAM write register... don't need to initialize

  STZ $211A		;clear Mode7 setting

  LDX #$211B
_Loop02:		;regs $211B-$2120
  STZ $00,X		;clear out the Mode7 matrix values
  STZ $00,X
  INX
  CPX #$2121
  BNE _Loop02

			;reg $2121 - Color address, doesn't need initilaizing
			;reg $2122 - Color data, is initialized later

  LDX #$2123
_Loop03:		;regs $2123-$2133
  STZ $00,X		;turn off windows, main screens, sub screens, color addition,
  INX			;fixed color = $00, no super-impose (external synchronization),
  CPX #$2134	;no interlaced mode, normal resolution
  BNE _Loop03

			;regs $2134-$2136  - multiplication result, no initialization needed
			;reg $2137 - software H/V latch, no initialization needed
			;reg $2138 - Sprite data read, no initialization needed
			;regs $2139-$213A  - VRAM data read, no initialization needed
			;reg $213B - Color RAM data read, no initialization needed
			;regs $213C-$213D  - H/V latched data read, no initialization needed

  STZ $213E		;reg $213E - might not be necesary, but selects PPU master/slave mode
			;reg $213F - PPU status flag, no initialization needed

			;reg $2140-$2143 - APU communication regs, no initialization required

			;reg $2180  -  read/write WRAM register, no initialization required
			;reg $2181-$2183  -  WRAM address, no initialization required

			;reg $4016-$4017  - serial JoyPad read registers, no need to initialize


  STZ $4200		;reg $4200  - disable timers, NMI,and auto-joyread

  LDA #$FF
  STA $4201		;reg $4201  - programmable I/O write port, initalize to allow reading at in-port

			;regs $4202-$4203  - multiplication registers, no initialization required
			;regs $4204-$4206  - division registers, no initialization required

			;regs $4207-$4208  - Horizontal-IRQ timer setting, since we disabled this, it is OK to not init
			;regs $4209-$420A  - Vertical-IRQ timer setting, since we disabled this, it is OK to not init

  STZ $420B		;reg $420B  - turn off all general DMA channels
  STZ $420C		;reg $420C  - turn off all H-MA channels

  STZ $420D		;reg $420D  - ROM access time to slow (2.68Mhz)

  LDA $4210		;reg $4210  - NMI status, reading resets

  

			;reg $4211  - IRQ status, no need to initialize
			;reg $4212  - H/V blank and JoyRead status, no need to initialize
			;reg $4213  - programmable I/O inport, no need to initialize

			;reg $4214-$4215  - divide results, no need to initialize
			;reg $4216-$4217  - multiplication or remainder results, no need to initialize

			;regs $4218-$421f  - JoyPad read registers, no need to initialize

			;regs $4300-$437F
			;no need to intialize because DMA was disabled above
			;also, we're not sure what all of the registers do, so it is better to leave them at
			;their reset state value

  JSR ClearVRAM      ;Reset VRAM
  JSR ClearPalette   ;Reset colors

  ;**** clear Sprite tables ********

  STZ $2102	;sprites initialized to be off the screen, palette 0, character 0
  STZ $2103
  LDX #$0080
  LDA #$F0
_Loop08:
  STA $2104	;set X = 240
  STA $2104	;set Y = 240
  STZ $2104	;set character = $00
  STZ $2104	;set priority=0, no flips
  DEX
  BNE _Loop08

  LDX #$0020
_Loop09:
  STZ $2104		;set size bit=0, x MSB = 0
  DEX
  BNE _Loop09

  ;**** clear WRAM ********

  STZ $2181		;set WRAM address to $000000
  STZ $2182
  STZ $2183

  LDX #$8008
  STX $4300         ;Set DMA mode to fixed source, BYTE to $2180
  LDX #wram_fill_byte
  STX $4302         ;Set source offset
  LDA #:wram_fill_byte
  STA $4304         ;Set source bank
  LDX #$0000
  STX $4305         ;Set transfer size to 64k bytes
  LDA #$01
  STA $420B         ;Initiate transfer

  LDA #$01          ;now set the next 64k bytes
  STA $420B         ;Initiate transfer

  PHK			;make sure Data Bank = Program Bank
  PLB

  CLI			;enable interrupts again

  LDX $4372  	;get our return address...
  STX $1FFD
  LDA $4374
  STA $1FFF
  RTL

wram_fill_byte:
.db $00

;----------------------------------------------------------------------------
; ClearVRAM -- Sets every byte of VRAM to zero
; In: None
; Out: None
; Modifies: flags
;----------------------------------------------------------------------------
ClearVRAM:
   pha
   phx
   php

   REP #$30		; mem/A = 8 bit, X/Y = 16 bit
   SEP #$20

   LDA #$80
   STA $2115         ;Set VRAM port to word access
   LDX #$1809
   STX $4300         ;Set DMA mode to fixed source, WORD to $2118/9
   LDX #$0000
   STX $2116         ;Set VRAM port address to $0000
   STX $0000         ;Set $00:0000 to $0000 (assumes scratchpad ram)
   STX $4302         ;Set source address to $xx:0000
   LDA #$00
   STA $4304         ;Set source bank to $00
   LDX #$FFFF
   STX $4305         ;Set transfer size to 64k-1 bytes
   LDA #$01
   STA $420B         ;Initiate transfer

   STZ $2119         ;clear the last byte of the VRAM

   plp
   plx
   pla
   RTS

;----------------------------------------------------------------------------
; ClearPalette -- Reset all palette colors to zero
; In: None
; Out: None
; Modifies: flags
;----------------------------------------------------------------------------
ClearPalette:
   PHX
   PHP
   REP #$30		; mem/A = 8 bit, X/Y = 16 bit
   SEP #$20

   STZ $2121
   LDX #$0100
ClearPaletteLoop:
   STZ $2122
   STZ $2122
   DEX
   BNE ClearPaletteLoop

   PLP
   PLX
   RTS

.ENDS
The 212c register you mentioned seems to be set to zero here.

Code: Select all

 LDX #$2123
_Loop03:		;regs $2123-$2133
  STZ $00,X		
  INX			
  CPX #$2134	
  BNE _Loop03
I tried putting stz $420B infront of the code but it still doesnt work for me. Theres still nothing in CGRAM when I look at it in vSNES.

But now that you see initsnes, perhaps you'll see something thats causing this problem? If the code I have is correct then I suppose I'm missing something critical that initsnes is doing...I'll try making my own simple initialization's if I get this problem out of the way.

Thanks again,
Nightcrawler
Romhacking God
Posts: 922
Joined: Wed Jul 28, 2004 11:27 pm
Contact:

Post by Nightcrawler »

byuu wrote:
The only thing I do differently is STOP DMA transfers BEFORE I load it up. You may be loading data into an active channel. So disable that channel beore loading up those registers and then enable it at the end as you did. When it comes to hacking games, this is unbelievably important. Usually you will wait for a channel to be free and inactive and then set it up, wait for vblank, and fire it off.
I've explained this to you before. stz $420b does absolutely nothing. When you enable a DMA channel, it starts transferring one opcode cycle later. It transfers all data, no matter how much there is, regardless if vblank is enabled or not, all at once, and CPU execution does not resume until all eight channels are clear.
stz $420c would clear HDMA. I'm not sure what would happen if you enabled DMA while HDMA was active. I imagine the DMA would disable the HDMA channel, though.
You're right. I apologize. I forgot that the CPU was paused during DMA on the SNES and had the misconception you could stop a transfer in progress.

You're still responsible for waiting for vblank before firing off DMA when writing to some of the PPU registers though, correct? I would assume usin DMA to write to VRAM would result in no data being written when outside of VRAM just like writing to it manually.
[url=http://transcorp.romhacking.net]TransCorp[/url] - Home of the Dual Orb 2, Cho Mahou Tairyku Wozz, and Emerald Dragon SFC/SNES translations.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
Nightcrawler
Romhacking God
Posts: 922
Joined: Wed Jul 28, 2004 11:27 pm
Contact:

Post by Nightcrawler »

Dan I'm not sure what's wrong with your code and I really don't have much time to sort through all this. And many people have trouble with WLA which I despise.

I did the code in xkas from sratch. Here is the fully functional code to generate the ROM to do what you are trying to do.

This is all you need. It works. I tested it.

As for the $212c register. It seems you don't need to enable a background unless you have chose a screen mode and/or done something with the screen registers.

Personally, I think it's bad practice to use the screen without explicitly setting it up, but it does work and I'm not 100% sure as to why. Im' so used to drawing tiles on the screen and to do that, you must initialize the background, screenmode, and VRAM addresses.


Anyway, here's the code that works. That's the best I can do for you. I have been doing SNES programming without issue with xkas for quite some time. It's simple, quick, and it works.

I've coded translation splash screens, some homebrew ROMs and countless hacks with it.

Code: Select all

lorom

org $8000 : fill $200000 ;pad some space on the image to make a ROM.

;add a quick header to the ROM
org $ffc0
  db 'ROM TITLE            '
  db $30   ;lorom ($31 = hirom)
  db $02   ;rom+save ram
  db $08   ;2mbit rom
  db $03   ;64kb sram
  db $00   ;japan
  db $00   ;no developer
  db $01   ;version 1.1
  dw $0000 ;inverse checksum
  dw $ffff ;checksum

  dw $ffff,$ffff,$ffff
  dw $ffff ;brk
  dw $ffff
  dw $8c00 ;nmi
  dw $ffff
  dw $8800 ;irq
  dw $ffff,$ffff
  dw $ffff ;cop
  dw $ffff,$ffff,$ffff
  dw $8000 ;reset
  dw $ffff

org $828000
db $ff,$ff	;Our palette data


org $8000
 
	sei             ;disable interrupts
	clc                     
	xce		;switch to native mode

	sep #$20	;8-bit accum
	rep #$10	;16-bit xy

	lda #$8f	
	sta $2100	;disable screen

	stz $210d	;initializes the scroll registers!! 
	stz $210d	;necessary on real hardware, but not on
	stz $210e	;emulators
	stz $210e

	lda #$00
	sta $2121   ; Start at color 0.

DMA:
	stz $4300   ;set up DMA transfer
	lda #$22	
	sta $4301   ;writing to PPU $2122	
	ldx #$8000
	stx $4302   ;source ofset $828000	
	lda #$82
	sta $4304
	ldx #$0002 
	sta $4305   ;writing 2 bytes
	lda #$01
	sta $420b   ;GO

	lda #$0f	
	sta $2100   ;enable screen
		
stop:
	bra stop
[url=http://transcorp.romhacking.net]TransCorp[/url] - Home of the Dual Orb 2, Cho Mahou Tairyku Wozz, and Emerald Dragon SFC/SNES translations.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
neviksti
Lurker
Posts: 122
Joined: Thu Jul 29, 2004 6:15 am

Post by neviksti »

Dan,
The mistake is not a conceptual one, but just a small typo.
In the DMA test code you posted, the line:
ldx $#0002 ;set size to 2 bytes

should be
ldx #$0002 ;set size to 2 bytes


That is all.
I tested it and it works fine.

-----------------------------
As a side note, Nightcrawler is of course correct that you do not need to setup all the registers ... just the ones you need. I don't even use that long InitSNES routine myself in actual projects, but it is useful for just playing around with quick progs to learn about the system (I do use stuff from the starter-kit at times when I just need to run a quick test).

As for the comment about WLA. He is also correct that it is "bulky". This bulk has a reason, but if you never intend to use those features, there are indeed better choices of assemblers.

I use WLA because I often do use those features. The great macro support really simplifies nasty repetative code and I use the macros for many other things as well (for example, as you can see in the starter-kit, I like to use the macros to handle automatic setup and tracking of common data objects I might load from files). Also, I really enjoy WLA for rom hacking because it allows me to assemble INTO an existing rom (some other assemblers have this feature as well), making insertion a breeze and keeps all my code changes conveniently together. And, while the "sections" can be annoying at the start, they have been a useful feature as well.

In the end, it is just a preference issue.
So Nightcrawler is right... check around a bit and choose the assembler that best suits your needs/projects.
byuu

Post by byuu »

Nightcrawler: I admit, it would be pretty awesome if DMA had its own bus and could run independantly of the CPU, but then you'd be exposing all sorts of bus conflict errors and in the end, it'd probably have just resulted in the SNES appearing way more "buggy" than the speedup would be worth. It's a common mistake though.

neviksti: xkas supports infinitely nested defines, labels, and even macros. And even the macros have a special "label" type that allow you to use the same macro more than once without a label conflict error. I don't know what you mean by tracking common data objects, but I do have debugging functions that let you print stuff to stdout from the assembler. And of course, xkas was written because at the time no other cross-assembler let you assemble directly into games, so you better believe xkas does that :)
Sections are annoying. One can use base+org to accomplish the same thing, and then warn to verify bank boundaries are not crossed. A macro could easily let you create a custom org function to support any memory map, but since this is used in <1% of SNES games, why make it mandatory for everything when "hirom" or "lorom" will do nicely?
I really do need to update xkas though, it's aging quite a bit...

e.x.
macro pc(addr)
org $addr ;do other funky stuff to addr here as needed, supports full c++-syntax manipulation, e.g. (addr+5*2)/8... whatever.
base $addr
endmacro

org $8000 becomes pc($8000)

But I agree, to each their own preference-wise. I'm pretty sure WLA handles the concept of object files a lot better than xkas. xkas was designed to assemble everything at once, but since it can tear through 120kb of assembler code in a quarter of a second even on a mid-range PC, I don't really see a need for the complexity of an object system.
neviksti
Lurker
Posts: 122
Joined: Thu Jul 29, 2004 6:15 am

Post by neviksti »

byuu wrote:I'm pretty sure WLA handles the concept of object files a lot better than xkas.
...
I don't really see a need for the complexity of an object system.
Yeah, I don't know anyone that actually uses that feature of WLA. Even on large projects it just doesn't seem worth it.

I admit that if xkas/spcas were around with those features when I was choosing an assembler pair, I probably would have been put off by wla's "setup" requirements and have chosen xkas/spcas.

I've been using WLA long enough that the "setup" requirements don't bother me (I just throw in a fairly standard file), and I've gotten so used to WLA's features that by now I don't see myself switching to a different feature set. However, if I ever start a new project, I think I'll give xkas/spcas a try.
smkdan
Hazed
Posts: 88
Joined: Sun Dec 19, 2004 4:55 am

Post by smkdan »

neviksti wrote:Dan,
The mistake is not a conceptual one, but just a small typo.
In the DMA test code you posted, the line:
ldx $#0002 ;set size to 2 bytes

should be
ldx #$0002 ;set size to 2 bytes


That is all.
I tested it and it works fine.
I didn't notice that I messed that part up...Well, I corrected it but despite the fact that it worked for you...it didnt work for me at all...Compiled with WLA 9.2 DX and the only thing I can think of is the version of the program. The debug snes9x tells me this about the transfer in 'what's missing'.

DMA 0 1 0x000000->0x2122 Num: 0 fixed
Read from unknown CPU register: $5A5A

vSNES still shows empty cgram.

Well, I guess I'll be trying xkas if all fails.
byuu

Post by byuu »

neviksti, it's fine. Use whatever you're comfortable with. To be honest, xkas really is more designed for romhacking than it is for programming new games, which is probably moreso what you use it for anyway.
e.g. lots of table funtionality built into there, and no minimal recompilation system for large projects.

I wouldn't switch assemblers or compilers even if I found a better one myself, as one tends to get really used to the intracacies of their current choice after years of using it. Not to mention all that old source code you can no longer edit...
neviksti
Lurker
Posts: 122
Joined: Thu Jul 29, 2004 6:15 am

Post by neviksti »

Dan wrote:DMA 0 1 0x000000->0x2122 Num: 0 fixed
Read from unknown CPU register: $5A5A
I'm not sure why it didn't work for you, and I don't immediately see what is even accessing $5A5A. So something got changed. If you send me a copy of all your source files I'll take a look at it if you wish.

However, if you run through the code with a single stepping debugger, or a trace logger that lists the register values/status as well (most do), I think the problem should become much more apparent.
Nightcrawler
Romhacking God
Posts: 922
Joined: Wed Jul 28, 2004 11:27 pm
Contact:

Post by Nightcrawler »

neviksti wrote:
Dan wrote:DMA 0 1 0x000000->0x2122 Num: 0 fixed
Read from unknown CPU register: $5A5A
I'm not sure why it didn't work for you, and I don't immediately see what is even accessing $5A5A. So something got changed. If you send me a copy of all your source files I'll take a look at it if you wish.

However, if you run through the code with a single stepping debugger, or a trace logger that lists the register values/status as well (most do), I think the problem should become much more apparent.
Absolutely. This is what I have been suggesting. Any assembly programmer NEEDS to be able to use a debgger. A debugger will tell you every single thing that is happening in your program.

I would recommend BSNES's debugger for this DMA test because it will show you when a DMA transfer happens. As Byuu said, you'll see it start one opcode after you enable the transfer.

Byuu
By the way Byuu, I don't fully understand all the debugging output that comes out in Red. What would you say this output actually is? Everything in blue is the actual 65c816 stuff step by step, and the read seems to be other things going on in the system such as the DMA transfer.
[url=http://transcorp.romhacking.net]TransCorp[/url] - Home of the Dual Orb 2, Cho Mahou Tairyku Wozz, and Emerald Dragon SFC/SNES translations.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
doktor_kris
Lurker
Posts: 102
Joined: Sat Feb 25, 2006 7:47 pm
Contact:

Post by doktor_kris »

Nightcrawler wrote:You should probably use BSNES, Super Slueth or SNEeSe for testing. They are the only emulators that properly emulate this portion of the system.
Though not perfect, Snes9x often produces the same (or close to)
problems/glitches as it would be on the real deal. It´d be nice if the
SNES itself was as forgiving as ZSnes. ;)
byuu

Post by byuu »

Byuu
By the way Byuu, I don't fully understand all the debugging output that comes out in Red. What would you say this output actually is? Everything in blue is the actual 65c816 stuff step by step, and the read seems to be other things going on in the system such as the DMA transfer.
Blue for 65816 opcodes, red for spc700 opcodes, green for debugging messages. The new debugger is taking that out, as using a richedit control results in too many annoying side effects :(
It's a shame because it makes reading just one or the other processor opcodes infinitely easier...
I can write my own control, but I can't do all the stuff windows controls do, such as highlight+copy on the textbox.
smkdan
Hazed
Posts: 88
Joined: Sun Dec 19, 2004 4:55 am

Post by smkdan »

A very silly mistake on my part...Apparently until I tried the bsnes debugger, initsnes was totally ignored and it jumped right to the start of the code. Apparently, without tabbing the macro, it wouldnt be used in the program and wla would give no warning...but oh well, stupid mistake from me :oops:

I may aswell continue posting my GFX questions here rather than starting a a new topic. Thanks for the help so far,btw.

So I got some understanding on the concept of writing tiles to the screen, tile map setup and BG setup.

I want to ask about the programs that simplify the process of making the GFX data. Particularly the tile maps. I cannot imagine myself manually inputting 2048 bytes for every 32x32 map so I had a look at pcx2snes (not like I have any other choice) from nevitski. I made a few files and I (sort of) got how it works.

For the output of the tilemap, which is the main reason Im not using ekid's converter, it seems to default to palette 0 with no option of changing it. Im using a screenfull pcx with the -screen option btw. I went through the read me and it shows of an option of 'palette re-arrangement' although the description doesnt seem clear to me. :oops:

I ask this because when I use say...BG mode 1 I may only be entitled to 16 colours of the first palette (0) rather than 8 palettes of 16 colours each to get a possible 128 colours for the BG.

Ofcourse, I may be missing something obvious here, yet again but it seems I may only use palette 0 from the output of the program. Hopefully im wrong on this since there isnt another tilemap output program like this from my searching.

Oh and another thing...say I want to time something, like a scrolling background, sprite,delay etc. Is there some sort of timing unit in the snes (just a farout guess...) or is there another thing to measure by? Im thinking that since Vblank / NMI occurs every frame, you could use this time various things? Say if I wanted to scroll a background / whatever at 60 pixels a second, I could increment the scroll register to move 1 pixel every time in a vblank routine? Or if I wanted 30 pixels a second, every 2nd vblank? Apparently Vblank time is painfully limited and not much can be done in the time, is there some other way or is vblank indeed the way to go for timings?

Thanks in advance, you've all been extremely helpful.
neviksti
Lurker
Posts: 122
Joined: Thu Jul 29, 2004 6:15 am

Post by neviksti »

I'm glad to hear you figured out the problems.
Dan wrote:I cannot imagine myself manually inputting 2048 bytes for every 32x32 map so I had a look at pcx2snes (not like I have any other choice) from nevitski.
There are other programs that do something similar.
But in the end it is worth reading about the graphics formats (these are explained in one of the documents in the starter kit). Plus this will allow you to make a tool more fit for your particular needs.
Dan wrote:For the output of the tilemap, which is the main reason Im not using ekid's converter, it seems to default to palette 0 with no option of changing it. Im using a screenfull pcx with the -screen option btw. I went through the read me and it shows of an option of 'palette re-arrangement' although the description doesnt seem clear to me. :oops:
I'm confused if you're talking about ekid's or my converter at the end there. Yes, my converter defaults to palette 0 (with no option of changing it) and it has a 'palette re-arrangement' option which is confusing. You have the gist of it though: in certain cases you can have more than say 16 colors on a 16 color BG because you have several palettes available to you. (But remember, you are still limited to only ONE palette on a tile, so usually given a random picture this does not help.) I've only used that option a couple times to test it and then never did anything with it ... so I wouldn't trust it too much.
Dan wrote:Apparently Vblank time is painfully limited and not much can be done in the time, is there some other way or is vblank indeed the way to go for timings?
For player interaction it doesn't really make sense to have a time unit less that what the player can see a response to. So yes, the "number of frames / VBlanks" is the natural time counter.

The VBlank time itself (not 1/60 of a second, but the actually time between drawing the last line of the screen and starting another frame) is indeed fairly short. So you don't want to be doing much calculation during this time. Usually the main loop of a program is something like

main loop:
get player input
handle interactions of elements in the game
update a buffer of the graphics info
wait for vblank
do loop again

vblank:
copy bufferred graphics changes to PPU as fast as possible
increment the "frame counter"
return from interrupt


So the main loop and vblank are both done only once every frame (1/60 sec for NTSC SNES) but while you don't have much time in VBlank, you have quite a bit of time in the main loop. Does that help clear it up? (Or did I misunderstand your question completely?)
smkdan
Hazed
Posts: 88
Joined: Sun Dec 19, 2004 4:55 am

Post by smkdan »

Ok, I got the Vblank details down and I seem to be getting somewhere with pcx2snes.

So I have a 24x8 PCX file with 3 tiles each using 3 'visible' colours and 1 transparent. This gives them 4 colours total each which I plan to insert into a mode 0 BG. I put into the cmd line 'pcx2snes tiles -screen -c4 -r'. the program reports successfully seperating into 3 palettes and and 2 tiles to use (one of the actual tiles, one for the blank space). But it seems that when I compile and run only the first tile looks correct, the other 2 are using totally different colours.

I looked in bsnes debug and saw the tile map looked right, the tiles looked right but the cgram contents were all wrong...Only 8 colours out of a needed 12 and only the first 4 colours were correct, so only the first tile looks right. The 2nd one has a broken mix of palette 0 and 1...Very odd. The 3rd one has no colour and only has black and the transparent colour in it (white).

Anything special I should keep in mind when saving the PCX or must it be something else here?

Thanks again,
creaothceann
Seen it all
Posts: 2302
Joined: Mon Jan 03, 2005 5:04 pm
Location: Germany
Contact:

Post by creaothceann »

Just checking... You know that in BG mode 0, each BG uses its own section of the palette?

Code: Select all

BG1 =  0.. 31
BG2 = 32.. 63
BG3 = 64.. 95
BG4 = 96..127
Might / might not be related.
vSNES | Delphi 10 BPLs
bsnes launcher with recent files list
neviksti
Lurker
Posts: 122
Joined: Thu Jul 29, 2004 6:15 am

Post by neviksti »

It's been quite awhile since I wrote that program, and even at the time the "palette rearrangement" feature wasn't something I really used. So while it may be an incorrect assumption, I'd just assume that it's the fault of my program. If you email me the picture and the code you are using to load and display it, I will update my program, test it with your code, and even add in a way to specify the pallette number like you wished. (shouldn't take too long)

Sound good?
Post Reply