I've been trying to get into the SNES dev scene, and have found:
Neviksti's starter kit, which uses WLA and isn't very organized. People don't seem to like it. I converted it to CA65, but am still not a fan.
Tepples' tutorial, which is very over complicated.
And uh. That's it. So what am I missing here, if anything? This doesn't seem like a very nice introduction to the 16-bit dev scene, and I'd like to stick around but there's no tutorials or anything that I can really follow.
Starting is as bad as you'd think... I started with Walker, did stuff to it, caused some bug that made it flip out so Koitsu converted what I did up to that point to ca65 and then I did more stuff to it. I guess if you want, I can give you what I've done so far and you can go backwards with it? (Or, you know, I can take features away instead of you doing so.)
The tutorials I used were bazz's tutorials (which unfortunately use WLA) and I also asked 101 questions here to get me where I am now. I'm sure you already know about this website, but here it is:
http://wiki.superfamicom.org/snes/show/HomePageI'm just saying, I hope you have better patience than I do...
nicklausw wrote:
Tepples' tutorial, which is very over complicated.
I'm willing to fix any too-steep gradient. What's the first thing you had trouble understanding?
The first problem I had was kind of my own problem: the makefile. It assumed a lot of programs that I don't have, and this might just be because I'm on Windows, but I needed to actually type in "python" before all the .py files to get them to run. Make knew to use python to open them, but kept trying with "env python" which uh...didn't work. It's fine now, but felt like some sort of rude awakening.
I've gotten the thing to build and taken out all APU stuff (don't care just yet,) so we'll see where this goes.
Looking through main...
line 17.
Code:
; OAMHI contains bit 8 of X and the size bit for each sprite.
X? What? I get the size bit thing, but have no idea what X is.
line 60.
Code:
lda #$4000 >> 13
sta OBSEL ; sprite CHR at $4000, sprites are 8x8 and 16x16
What's the deal with the shift 13 bytes or whatever that is?
What exactly is pseudo hi-res, and why is it optional? Same with interlace. Is this explained somewhere else?
The rest of that file kinda makes sense. I should probably just PM questions and suggestions for the rest of them.
Someone posted this link recently...
https://github.com/undisbeliever?tab=repositoriesI haven't looked closely at everything, but they appear to be a dozen small games written for SNES.
nicklausw wrote:
The first problem I had was kind of my own problem: the makefile. It assumed a lot of programs that I don't have
What did it assume beyond MSYS and Python? Are you using Cygwin Make, MSYS Make, or
mingw32-make? Fixing the instructions to install dependencies still counts as fixing the tutorial. I guess I'm just spoiled on Debian derivatives, where
sudo apt-get install python-imaging build-essential and then building the cc65 toolchain from source gives everything you need.
Quote:
Make knew to use python to open them, but kept trying with "env python" which uh...didn't work.
What
env does, as explained in answers to
TheGeeko61's question, is let the shebang line (
#!/path/to/program) processor search the
PATH for the Python interpreter rather than hardcoding an install location. I was sure
env came with MSYS. (Does it?)
Quote:
X? What? I get the size bit thing, but have no idea what X is.
I'm sorry; I just assumed that anybody who has studied computer graphics would have known what an
X coordinate was.
Quote:
What's the deal with the shift 13 bytes or whatever that is?
The sprite pattern table starts $4000 words from the start of video memory. But the
OBSEL register needs the address of the sprite pattern table to be given in $2000-word units, and the right shift by 13 bits divides the address by $2000.
Quote:
What exactly is pseudo hi-res, and why is it optional? Same with interlace. Is this explained somewhere else?
Features that the demo doesn't really use, but you can turn on when building the demo to see what they do. Both are explained in the
list of MMIO ports on wiki.superfamicom.org.
tepples wrote:
What did it assume beyond MSYS and Python? Are you using Cygwin Make, MSYS Make, or mingw32-make?
I'm using mingw32-make. The programs assumed were sed (had to copy from cygwin to C:\Windows,) pwd (had to make a batch file under C:\Windows,) and bsnes and something else. Should I be using something other than the command line? Cygwin broke in half when trying to use the makefile, so.
tepples wrote:
What
env does, as explained in answers to
TheGeeko61's question, is let the shebang line (
#!/path/to/program) processor search the
PATH for the Python interpreter rather than hardcoding an install location. I was sure
env came with MSYS. (Does it?)
The MSYS shell...uh...maybe I shoulda thought of that. Don't seem to have it, though...
tepples wrote:
I'm sorry; I just assumed that anybody who has studied computer graphics would have known what an
X coordinate was.
The sarcasm, man, it hurts. I see what you mean now though.
tepples wrote:
The sprite pattern table starts $4000 words from the start of video memory. But the OBSEL register needs the address of the sprite pattern table to be given in $2000-word units, and the right shift by 13 bits divides the address by $2000.
So this could be done with lda #$4000/$2000?
tepples wrote:
Features that the demo doesn't really use, but you can turn on when building the demo to see what they do. Both are explained in the
list of MMIO ports on wiki.superfamicom.org.
Fair enough.
Update: the MSYS shell (which I do in fact have apparently) handles all the Unix problems.
nicklausw wrote:
tepples wrote:
What did it assume beyond MSYS and Python? Are you using Cygwin Make, MSYS Make, or mingw32-make?
I'm using mingw32-make. The programs assumed were sed, pwd, and bsnes and something else.
The
sed and
pwd are needed for use of NO$SNS in Wine. Most Windows programs accept paths with either forward slashes or backslashes, and most Windows programs accept paths relative to the current directory. This means I can easily run them in Wine from a UNIX makefile. But the command line parsing in Martin Korth's NO$SNS emulator is quirky in that it requires an absolute path to the ROM, not a path relative to the current working directory. So it needs to use
pwd to retrieve the name of the directory where the makefile resides and
sed to convert it from a UNIX path, with forward slashes and no drive letter, to a Windows path, with backslashes and a drive letter, suitable to pass to NO$SNS filenames to be passed on the command line. They shouldn't be needed for an emulator that has more sane command line processing, such as bsnes. That's why I made
EMU a variable, so that the user of the makefile could customize the choice of emulator. The big reason I use NO$SNS at all is that it's the only debugging emulator I know of that runs full-speed on my Dell Inspiron mini 1012 laptop's Atom CPU.
Quote:
Should I be using something other than the command line? Cygwin broke in half when trying to use the makefile, so.
As you ended up discovering while ninjaing this very post, MSYS is lighter weight than Cygwin but still provides enough of GNU Coreutils to run typical makefiles. From README.md:
- Visit devkitPro Getting Started.
- Follow the instructions there to download and run the devkitPro Automated Installer.
- In the installer, check only MSYS.
Is there a way I could have made it even clearer that yes, Windows users should be using MSYS?
Quote:
tepples wrote:
The sprite pattern table starts $4000 words from the start of video memory. But the OBSEL register needs the address of the sprite pattern table to be given in $2000-word units, and the right shift by 13 bits divides the address by $2000.
So this could be done with lda #$4000/$2000?
Yes it could. But at the time, I thought it might confuse people who aren't accustomed to seeing division in assembly language. They might think it's some sort of other separator, much as the Apple IIGS Monitor (aka
CALL -151) separates the bank (A23-A16) from the rest of the address (A15-A0) with a slash. The
>> 13 emphasizes that bits 14 and 13 of the address are going into bits 1 and 0 of
OBSEL. Or I could add a comment near every bit shift in a similar context that "Alternatively, this could be interpreted as a division by whatever"; would that make things clearer?
Ya got me, I didn't look very well through the readme. Sorry about that.
Quote:
Yes it could. But a lot of people aren't accustomed to seeing division in assembly language; they might think it's some sort of other separator. The >> 13 emphasizes that bits 14 and 13 of the address are going into bits 1 and 0 of OBSEL. Or I could add a comment near every bit shift in a similar context that "Alternatively, this could be interpreted as a division by whatever"; would that make things clearer?
That's a very odd thing to assume that people would know. A comment would certainly help, as without it, I doubt many people would know what's going on.
Thanks for the feedback. I've added comments to those places in the tree that will become 0.06.
Out of curiosity, why don't you have the template up on GitHub or some other git client? Feels like changes would be a lot easier to manage that way, and feedback would be less tedious to give. (imo, that is).
Because then I'd have to set aside a few hours to learn how to Git.
tepples wrote:
Because then I'd have to set aside a few hours to learn how to Git.
Ah, I see. Git wasn't drastic to figure out for me, just the weird terminology had me caught up for a while. Yeah, though, if you lack time then maybe stick to what you're doing.
There's also bass, xkas, and asar, for those who want to be able to move the direct page around.
bass is a great assembler by byuu, and has an active support forum here:
http://board.byuu.org/phpbb3/viewforum.php?f=20
psycopathicteen wrote:
There's also bass, xkas, and asar, for those who want to be able to move the direct page around.
Not the slightest impossible with ca65. Just use the z:-modifier and you're set.
Here (in the SFX_INIT_mmio function) I do the canonical PPU initalization using direct page addressing with some helper macros.
Digging up my old questions thread because there's no need for a new one.
Does anyone know if there's a good way to make SNES graphics other than the combination of aseprite and pcx2snes?
I've been thinking about making my own little snes paint program. I'd just need to know how the system's palette works, and iirc it's 15-bit bgr? And I saw a page on wiki.superfamicom.org that teaches conversion between that and 24 bit color.
Also are SNES tiles 4bpp, 8bpp...?
SNES sprites are always 4bpp.
SNES background tiles are selectably 2bpp, 4bpp, or 8bpp, and each background tile is selected from one of eight different palettes.
nicklausw wrote:
Does anyone know if there's a good way to make SNES graphics other than the combination of aseprite and pcx2snes?
I use YY-CHR for all my console tile editing needs (which includes SNES support)... dunno if it'll be the right fit for you, but it's an alternative.
nicklausw wrote:
Does anyone know if there's a good way to make SNES graphics other than the combination of aseprite and pcx2snes?
I don't know what aseprite is, but I just use Gimp (it can create indexed images, and you can sort around the colors) and pcx2snes. It works fine, but the color converting can be annoying. (I don't think there's a way to make Gimp work in 15 bit color.)
nicklausw wrote:
it's 15-bit bgr?
Yes. I'm pretty sure the unused bit is the highest one, so it looks like
0bbbbbgg gggrrrrr
nicklausw wrote:
Also are SNES tiles 4bpp, 8bpp...?
2bpp, 4bpp, and 8bpp. Sprites are always 4bpp, while BG layers can be any of these color depths.
If you want to know the graphics format (it would probably be useful for this program of yours) I think it's like this:
Code:
2bpp 00 00 00 00
4bpp 00 00 00 00
00 00 00 00
8bpp 00 00 00 00
Basically, 4 4bpp pixels are set up like 8 2bpp pixels, if that makes sense. The space between the 0's (which are the bits) are the boundaries of where a pixel ends and a new one starts. Does that make sense to you? I don't really know how to explain it.
Luckily though, with mode 7, it's a much easier to understand format in that 1 pixel is just 8 bits across. Map data is interweaved with the tile data, byte per byte, although I'm not sure the order.
Anyway, I think that's about it. I'm probably accidentally giving you false information...
Wow, lidnariq beat me while I was writing this...
nicklausw wrote:
I've been thinking about making my own little snes paint program.
Why ? Gimp or Photoshop is not enough?
nicklausw wrote:
Does anyone know if there's a good way to make SNES graphics other than the combination of aseprite and pcx2snes?
I do'nt know these tools, allows aseprite to do what?
I find it strange to make pcx2snes, I find the png more convenient.
I use a png / snes conversion tools, with option for pallete.
Quote:
it's 15-bit bgr?
yes, the conversion is so easy to do.
Alright, thanks, it looks like YY-CHR's C# version suits my needs. Thanks to tepples' tutorial I've got the palette loaded, now the 4bpp font...
The tile format is weird to someone used to the NES. (Actually, it's weird regardless.)
It's a 16-bit format, probably because of the way VRAM is set up. The first byte is the first bitplane of the first 8x1 sliver of a tile. The second byte is the second bitplane of the same sliver. Then the third byte is the first bitplane of the second sliver, and the fourth byte is the second bitplane of the second sliver, on to the end of the tile (16 bytes). If the BG layer in question is 2bpp, you're done. If not, the whole pattern repeats from the top of the tile for the third and fourth bitplanes, for another 16 bytes. For sprites and 4bpp BG layers, that's the whole story, but for 8bpp backgrounds that whole story repeats to provide the last four bitplanes. So a 4bpp tile is two 2bpp tiles in a row, and an 8bpp tile is four 2bpp tiles in a row.
Also, obviously 8bpp graphics can't select subpalettes. Unless you're using direct colour, which uses the palette selector bits to add colour depth.
8bpp, is that modes 3-4 (256 color BG)? And maybe mode 7?
What's direct colour?
Also, I said it earlier, and I'll say it again. It would be great of someone made a NES screen tool style tile arranger tool for the SNES.
Yes, BG1 is 8bpp in Modes 3, 4, and 7.
Direct colour mode can be set via $2130, and only works on 8bpp backgrounds. It uses what would have been the 8-bit index into CGRAM as RGB332 (well, strictly BB000GGG00RRR00), and the palette selector bits are used to expand that to RGB443 (BBb00GGGg0RRRr0, but the 'bgr' is per-tile instead of per-pixel). Note that the Mode 7 tilemap doesn't have palette selector bits, so you're stuck with RGB332 if you're using direct colour in Mode 7.
http://problemkaputt.de/fullsnes.htm#sn ... rectcolorshttp://wiki.superfamicom.org/snes/show/Backgroundshttp://wiki.superfamicom.org/snes/show/Registers
Ok. I had to read your explanation 4 times, but I think I get it. In 256 color modes, each pixel uses 8 bits to define a color. Rather than indexing from the palette, those 8 bits defines the color itself. But, with fewer color options, since it only defines 2,3,3 (8 bits) for a color rather than a full palette entry 5,5,5 (15 bits) for a color.
And this sounds like something that I would not want to do, because 256 seems like enough colors to choose from.
Edit, actually... maybe it would be much easier to write a tool to convert a full color picture to SNES pixels if I were using direct color mode. Hmm. I'll have to experiment some day, and see what kind of results that gets.
Sorry; I see now how that could have been hard to read.
Just a clarification (it doesn't sound like you need it, but I've seen people screw this up and you aren't the only person reading this thread): An 8bpp layer is normally indexed; it uses all of CGRAM as its palette. Direct colour is an option for those layers, not the default behaviour.
And I'm pretty sure it's not a popular option. I think 8bpp indexed tends to look better, since you have free choice of all the colours in the RGB555 master palette. But I'm sure there's an application for this feature hiding somewhere...
dougeff wrote:
Edit, actually... maybe it would be much easier to write a tool to convert a full color picture to SNES pixels if I were using direct color mode. Hmm. I'll have to experiment some day, and see what kind of results that gets.
Direct-color mode isn't terribly useful for things as simple as that: you can think of it as one specific pregenerated palette that you could also have explicitly uploaded to CGRAM. (There's also been hundreds of different kinds of algorithms for determining a set of colors to use with truecolor-to-palette conversion. e.g. those algorithms used by
mtpaint,
animmerger,or
Display, almost all of them produce better results than just static non-adaptive rgb332)
The only thing that comes to mind is that you could use a direct-color 8bpp plane
with a separate palette for sprites and a 2/4bpp tile layer, but you might just be in danger of running out of memory for tiles at that point.
Okay, does anyone know how I can:
1. Set the background to be 4bpp?
2. Write to the background?
I'm not really concerned with crazy layers and stuff, unless there's some special reason I should be.
Quote:
1. Set the background to be 4bpp?
it depends on the mode.
For example :
Mode 0, 4 BG(1,2,3,4) in 2 bpp
Mode 1, 2 BG(1,2) in 4bpp and 1 BG(3) in 2bpp
Quote:
2. Write to the background?
Where you want ,simply configure with:
BG1SC,BG2SC,BG3SC,BG4SC ($2107-$210A) for tile
BG12NBA BG34NBA ($210B/$210C) for data
You have to read the documentation, everything is there.
I say this because many SNES option.
Alright, writing to the BG seems simple enough, but when it comes to the modes, how would I actually go about switching to mode 1? tepples' example uses mode 0 I'm pretty sure, so that doesn't really help.
EDIT: I'm stupid...mode 0 seems to suit my needs just fine after all.
must write on BGMODE ($2105).
Code:
;mode 0
lda #00
sta $2105
;mode 1
lda #01
sta $2105
;mode 1 and BG1 16x16
lda #11
sta $2105
Set the mode with register 2105
---- -mmm
Mode 1 and 2 use 4 bpp.
The second part takes about 10 steps to do, and I'm no expert...
-force blank
-put BG tile graphics in VRAM
-put BG tilemap in VRAM
-tell it were the BG graphics are
-tell it were the BG map is
-fill palette
-turn off mosaic
-set scroll
-allow rendering, and set brightness
lda #$1f
sta $212C ;enable main screen
Did I forget anything?
nicklausw wrote:
I'm not really concerned with crazy layers and stuff, unless there's some special reason I should be.
I'm not getting it... There are several video modes on the SNES that just arrange how the vram bandwidth is being used. Here's a good link to look at for it:
http://wiki.superfamicom.org/snes/show/Backgrounds (some video modes have special properties like column scrolling, like modes 2 and 4). Mode 1 is (by far) the most often used, but Mode 3 is another good one. The major drawback to mode 7 is the fact that there's only one BG layer (the mode 7 plane) and also the fact that there's only 256 tiles to choose from (and no horizontal or vertical flipping).
Assuming you want to use mode 1, do these steps to enable the BG layer: (here's a good link to learn more about these hardware registers:
http://wiki.superfamicom.org/snes/show/Registers)
Code:
lda #$01 ;Set video mode 1, )(16 color BG1, 16 color BG2, 4 color BG3) 8x8 tiles (changing bit 5 will make the tiles 16x16)
sta $2105
lda #%??????00 ;Set BG1's Tile Map VRAM offset to #%??????>>10 (word address) and the Tile Map size to 32 tiles x 32 tiles (the first 0 doubles the width of the tilemap, the second doubles the height of the tilemap)
sta $2107
lda #$0? ;Set BG1's Character VRAM offset to #$?>>12 (word address) (the 0 is for BG2)
sta $210b
lda #$01 ;Turn on BG1
sta $212C
God damn, I was writing all this and people beat me to it...
nicklausw wrote:
tepples' example uses mode 0 I'm pretty sure, so that doesn't really help.
I'd make a mode 1 example if I had examples of background artwork that needed mode 1. But my pixel art skills are still very much stuck in the NES/GBC/NGPC days.
dougeff wrote:
The second part takes about 10 steps to do, and I'm no expert...
That sounds reasonable. And in fact, all but brightness and mosaic are also things you have to do on the NES as well.
Quote:
Did I forget anything?
Some time ago, I posted a
list of everything you need to do to bring up a picture on the NES PPU or Super NES S-PPU.
tepples wrote:
I'd make a mode 1 example if I had examples of background artwork that needed mode 1. But my pixel art skills are still very much stuck in the NES/GBC/NGPC days.
I can help there, but no promises. I think mode 0 might be somewhat useful if you have something with very low contrast, like a dark cave
Heres a slightly better description of displaying a BG...
$8x to 2100 force blank
$01 to 2105 set mode 1
$00 to 2106 mosaic off (1x1)
2115-9 Put BG graphics and tilemaps in VRAM (or use a DMA transfer)
2107 set BG1 tilemap address and size
(2108 set BG2 tilemap address and size)
210b set BG1/2 graphics address
210d-e set BG1 scroll
(210f-10 set BG2 scroll)
2121-2 write palette
(Optional, display sprites...)
2115-9 Put sprite graphics in VRAM (or use DMA transfer)
2101 set Oam size and VRAM location
2102-4 Put sprite data in OAM
$0f to 2100 enable rendering, full brightness
$1f to 212c, set all to 'main screen'
And I think you need to turn off scanline IRQs...4200
I think window masks and color math are off by default, so you don't have to set them.
Again, I'm new at this, so let me know if I made any mistakes or omissions. Thanks.
dougeff wrote:
I think window masks and color math are off by default, so you don't have to set them.
Shouldn't everything be off by default? That's what the initialization routine is for.
Okay, so this is what I have so far, and what's happening is that a 5 is displaying on the screen, but:
1. it only appears about half the time in higan?
2. it doesn't seem to use the full palette (can't mode 1 have sixteen colors? It only uses one, even with the palette properly loaded).
EDIT: the full palette is used but while no$sns uses it properly, higan seems to have the colors all weird...
Here's the code for loading all this VRAM stuff:
Code:
; forced blank
seta8
lda #$8f
sta PPUBRIGHT
lda #$01
sta BGMODE ; mode 0 (four 2-bit BGs) with 8x8 tiles
stz BGCHRADDR ; bg planes 0-1 CHR at $0000
lda #$4000 >> 13
sta OBSEL ; sprite CHR at $4000, sprites are 8x8 and 16x16
lda #>$6000
sta NTADDR+0 ; plane 0 nametable at $6000
sta NTADDR+1 ; plane 1 nametable also at $6000
; Copy background palette to the S-PPU.
; We perform the copy using DMA (direct memory access), which has
; four steps:
; 1. Set the destination address in the desired area of memory,
; be it CGRAM (palette), OAM (sprites), or VRAM (tile data and
; background maps).
; 2. Tell the DMA controller which area of memory to copy to.
; 3. Tell the DMA controller the starting address to copy from.
; 4. Tell the DMA controller how big the data is in bytes.
; ppu_copy uses the current data bank as the source bank
; for the copy, so set the source bank.
seta8
stz CGADDR ; Seek to the start of CGRAM
setaxy16
lda #DMAMODE_CGDATA
ldx #palette & $FFFF
ldy #palette_size-palette
jsr ppu_copy
; Copy background tiles to PPU.
; PPU memory is also word addressed because the low and high bytes
; are actually on separate SRAM chips.
; In background mode 0, all background tiles are 2 bits per pixel,
; which take 16 bytes or 8 words per tile.
setaxy16
stz PPUADDR ; we will start video memory at $0000
lda #DMAMODE_PPUDATA
ldy #font_size-font
ldx #font & $FFFF
jsr ppu_copy
lda #$6000|NTXY(1,1)
sta PPUADDR
lda #'5'
sta PPUDATA
seta8
lda #%00000001 ; enable sprites and plane 0
sta BLENDMAIN
lda #$0F
sta PPUBRIGHT
?forever:
jmp ?forever
And here's the 'borrowed' initialization code:
Code:
sei ; Disable interrupts
clc ; Clear carry, used by XCE
xce ; Set 65816 native mode
jmp :+ ; Needed to set K (bank of PC) properly if MODE 21 is ever used;
; see official SNES developers docs, "Programming Cautions"
: cld ; Disable decimal mode
phk ; Push K (PC bank)
plb ; Pull B (data bank, i.e. data bank now equals PC bank)
rep #$30 ; A=16, X/Y=16
; Note: this should correlate with ZEROPAGE in snes.cfg
lda #$0000
tcd ; Set D = $0000 (direct page)
; Note: this should correlate with the top of BSS in snes.cfg
ldx #$1fff
txs ; Set X = $1fff (stack pointer)
; Register initialisation values, per official Nintendo documentation
sep #$20 ; A=8
lda #$80
sta $2100
stz $2101
stz $2102
stz $2103
stz $2104
stz $2105
stz $2106
stz $2107
stz $2108
stz $2109
stz $210a
stz $210b
stz $210c
stz $210d
stz $210d
stz $210e
stz $210e
stz $210f
stz $210f
stz $2110
stz $2110
stz $2111
stz $2111
stz $2112
stz $2112
stz $2113
stz $2113
stz $2114
stz $2114
lda #$80
sta $2115
stz $2116
stz $2117
stz $211a
stz $211b
lda #$01
sta $211b
stz $211c
stz $211c
stz $211d
stz $211d
stz $211e
lda #$01
sta $211e
stz $211f
stz $211f
stz $2120
stz $2120
stz $2121
stz $2123
stz $2124
stz $2125
stz $2126
stz $2127
stz $2128
stz $2129
stz $212a
stz $212b
stz $212c
stz $212d
stz $212e
stz $212f
stz $4200
lda #$ff
sta $4201
stz $4202
stz $4203
stz $4204
stz $4205
stz $4206
stz $4207
stz $4208
stz $4209
stz $420a
stz $420b
stz $420c
stz $420d
;ClearVram
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
LDX #.LOWORD(zero_fill_byte)
STX $4302 ;Set source address to $xx:0000
LDA #.BANKBYTE(zero_fill_byte)
STA $4304 ;Set source bank
LDX #$0000
STX $4305 ;Set transfer size to 65536 bytes
LDA #$01
STA $420B ;Initiate transfer
;ClearPalette
STZ $2121
LDX #$0100
ClearPaletteLoop:
STZ $2122
STZ $2122
DEX
BNE ClearPaletteLoop
;**** 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 SNES RAM ********
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 #.LOWORD(zero_fill_byte)
STX $4302 ;Set source offset
LDA #.BANKBYTE(zero_fill_byte)
STA $4304 ;Set source bank
LDX #$0000
STX $4305 ;Set transfer size to 64KBytes (65536 bytes)
LDA #$01
STA $420B ;Initiate transfer
LDA #$01 ;now zero the next 64KB (i.e. 128KB total)
STA $420B ;Initiate transfer
What all is the deal here, anyway?
Is "seta8" (etc) an assembler directive (to assemble in 8/or 16 bit modes)? Because you also need to use SEP and REP to put the processor in the correct mode.
Yeah, "seta8" and "setaxy16" are both macros to use SEP and REP to do such.
Update: for the sake of flat out letting you all see what exactly I'm doing,
here's a github repo with it all. The makefile should work given that ca65, ld65, bsnes, and superfamicheck are in your path. And you're on linux. Probably not yes to both unless you're lucky. The project can easily be built manually, though.
I see you are also working on an SNES assembler. Did you know that Disch wrote an SNES assember last year...
http://www.romhacking.net/forum/index.p ... 086.0.htmlAlso, since you gave us the source code, would you be able to post a link to the compiled .sfc file that you're having trouble with?
I'd like to take a close look at it, make sure you're not getting some kind of assembler error.
dougeff wrote:
I see you are also working on an SNES assembler. Did you know that Disch wrote an SNES assember last year...
http://www.romhacking.net/forum/index.p ... 086.0.htmlAlso, since you gave us the source code, would you be able to post a link to the compiled .sfc file that you're having trouble with?
I'd like to take a close look at it, make sure you're not getting some kind of assembler error.
Done. (in the repo, click on basic.sfc and click "View Raw" to download)
I've noticed in your .cfg file you defined 4 banks of $8000, total $20000.
I believe the smallest SNES ROMs are 2Mbit /8 = (262,144) or $40000 bytes. Shouldn't you have a minimum 8 banks of $8000 ?
Edit. On searching the web, I see some 1 Mbit chips available, so maybe I'm completely wrong.
This is true, 128k roms technically shouldn't be a thing, I might as well change that.
This has no effect on the problem I'm having with higan, however.
I edited my above statement while you were typing.
I would test out the rom on higan 9.5 (older version) to see if this is a new thing in the emulator, but the emulator didn't get support for loading ROMs outside its library system until the newest version...and the library system doesn't get along well with wine.
Well, I checked the entire assembly, and it matches the source code. It seems to work fine in everything except Higan Accuracy.
I'm looking at the save state (Higan) at what appears to be the palette. The color here is listed as ff7f = white, but the screen is displaying a pink. I'm trying to think of what would cause the palette to display wrong. Hmm?
The problem is not 2130 or 2133.
I'm wondering if Higan is flawed.
No emulator is perfect, but I'd put odds at 99:100 it's a bug in your code.
Make sure you are properly initializing -all- registers. That's the main thing that breaks games in accuracy; it aggressively randomizes all registers/memory to detect these bugs.
Well, I replaced your startup code with a different set that I know works, and sets all registers, and zeros every RAM and VRAM and CGRAM byte. Still get the same weird colors in Higan Accuracy. So, the problem is not your startup code.
This one has stumped me.
I also know exactly which byte of the save-state is the problem $463b7. Changing this byte and reloading save-state causes the weird color issue. I have no idea what this part of the save-state is. I even peeked at the source code of Higan. Still no idea.
It's not the palette. It's not color math or color intensity or color brightness or windows or any other thing that would reasonably affect color.
The startup code is working. The palette is correctly set. The graphics are correctly loaded. The base addresses are correct. Only BG1 is active, so no other backgrounds are interfering.
This one is unsolvable.
Might I respectfully suggest trying it out on an actual SNES? If the "unexpected" behaviour is the same there, then it's definitely a programming mistake and not an emulator quirk (and thus should be taken seriously). If you can provide an actual ROM image I can try this out for you, assuming I'm told what exactly to look for.
koitsu wrote:
If you can provide an actual ROM image I can try this out for you, assuming I'm told what exactly to look for.
What constitutes an "actual ROM image"?
The sfc is here, I'm not sure if you need it in some other format or anything.
As for what to look for, what's supposed to happen in this: in the top left corner of the screen, the number '5' is drawn and is white. In higan-accuracy, however, sometimes the number doesn't show up or shows up with a different color. (Note, I can now confirm that this isn't an OS-specific thing). I just want to know which one is correct.
Where can I get a snes flashcart of my own, anyway? I hear they're expensive.
nicklausw wrote:
What constitutes an "actual ROM image"?
The sfc is here, I'm not sure if you need it in some other format or anything.
Nope, that's perfectly fine and exactly what I was wanting.
nicklausw wrote:
As for what to look for, what's supposed to happen in this: in the top left corner of the screen, the number '5' is drawn and is white. In higan-accuracy, however, sometimes the number doesn't show up or shows up with a different color. (Note, I can now confirm that this isn't an OS-specific thing). I just want to know which one is correct.
Thanks, that's all I need.
I'll try to test this out either later tonight or on Tuesday, as I don't have much spare time today/tomorrow afternoon.
nicklausw wrote:
Where can I get a snes flashcart of my own, anyway? I hear they're expensive.
The two most popular are the Super EverDrive and the SD2SNES. I can only speak to the reliability and quality of the
SD2SNES (I wanted something that had a very good menu interface and something that felt better designed), which I bought from Krikzz directly. The devices range from about US$80 to $200, depending on what all you want on them (I paid $190 for mine, which included a proper cartridge case); the Super EverDrive is less expensive.
I've discussed in the past (can't find the post now though, sorry) how these prices are *ridiculously* cheap compared to what we paid for similar devices in the early 90s (the original/major snesdev days), so I don't wanna hear any whinging about how expensive they are -- they're pocket change comparatively, while being significantly more convenient, reliable, and faster than old SNES copiers (which usually went for US$450-800).
If you want one and can't afford it, give me a PayPal address (send me a PM) and I'll be happy to donate money, no strings attached, that'll get you the Super Everdrive. I did this for user
93143 here on the forum to help with his homebrew efforts. I always believe in supporting homebrewers any way I can. It's honestly too bad the tools folks have nowadays for SNES homebrew are almost seem worse than what we had in the 90s -- count your small blessings (SNES9x debug build, no$sns, YYCHR). But you really need to test your code on the actual thing -- emulators are fine for general development and "hey it works!" scenarios, but you should always make sure it works on the real thing.
koitsu wrote:
But you really need to test your code on the actual thing -- emulators are fine for general development and "hey it works!" scenarios, but you should always make sure it works on the real thing.
Unfortunately, copiers and flash cartridges are still not ideal for development, since they temper with the power up state of the machine, so you can't be absolutely sure your code would work when running from a regular cartridge. This is not a big problem though, since the initialization process is much simpler to fix than the game engine itself. Just make sure you or someone else can test the final game in a standalone cartridge before considering it 100% compatible with the actual hardware.
Hey, I see that you've gone off and done other things for 4 pages of this forum thread, but I wrote some tutorials about 10 years ago and it looks they are still
"very helpful". I also recognize you from WLA-DX Github, and my tutorials employ WLA DX, so you can't really go wrong there
Yeah, I have a very mixed relationship with wla-dx. It's the only assembler I've ever contributed to, but at the same time I refuse to use it for 65xx development simply because it's not meant for it. It can be used for gameboy development (it was originally designed for it actually) but rgbds is just more common (and fully designed around the gameboy,) so I use that instead for convenience. The Sega 8 bit community has WLA on lock-down, though; it's the best assembler there. Of course, I haven't worked with a Sega system in forever now, so basically I don't use it.
Right, well I'm not really here to advocate use of any assembler -- I don't care -- but I do still believe there is something special about my tutorials. To be precise, if you use your own assembler and build scripts, I bet you could still learn better from my tutorials -- skipping over any WLA DX specifics -- but the source code would also need to be ported to your flavor.
In fact -- if anyone decides to port my tutorials source code to another assembler, feel free to include the project files as zip archives, in the same fashion the WLA-DX ones are! Eventually, the tutorials could be broken into "Assembler specifics" (ie. memory map / build scripts for assembler "foo") and "General SNES Tutorial" parts -- well it's an idea for somebody
I'd like to elaborate why I think my tutorials are awesome -- when I started them, I had no idea about any Electrical Engineering. I had programmed in C, and learned z80 asm to get myself ready -- but still -- the tutorials come from the perspective of someone (me) who is thinking "WTF is all this shit" -- OH! this is what this is and how this works!! *check it out everyone -- this is how this works!! and you do this and THAT'S why it does THAT!!* hehe, and I think that style was well-received by people. A lot of people like me who saw the SNES and were so inspired by it, who wanted to program it, probably also had no prior EE experience - and to explain these things so practically as they were just learned by me I think was delightful.
Before I had written those tutorials -- there were mostly only register reference documents, and eventually a leaked Nintendo manual became more popularly circulated -- and memory map documents were there -- but it was extremely non-obvious how all that connected -- especially to someone with no EE / embedded programming experience. Anyone's best shot was to analyze the "starter kits" that had project files that connected all the dots -- and even THAT was insanely difficult.. My tutorials were a result of being so stubborn that I just kept analyzing those files and assembler documentation and memory map etc. until more things started making sense..
I eventually went on to get into hardware, making stuff like GB Flasher and my own SNES flash cart/programmer -- and let me tell you -- seeing how the hardware works puts EVERYTHING into perspective. (ie. Address bus / Data bus). Getting into SNES catapulted me into a future being able to work with embedded systems running on ARM chips - and now I can reverse engineer even modern systems! But I'm getting into my life story so I'll stop here.
I more or less agree with bazz's sentiments and story, although I don't do "howtos/walkthroughs" -- I will be egocentric and say that I'm remarkably good about writing technical documentation (and not just for consoles), but I am not a good teacher. So it makes me happy to see someone who took the time to take care of the "teaching" part in a way people can understand.
On the flip side, in comparison to bazz, I have little to no interest in the EE/hardware side of things. While I get general concepts (address lines, data lines, and some other related bits), my eyes gloss over and I want to let out a resounding fart whenever deep/low-level hardware aspects comes into discussion; more specifically, the instant someone busts out a board/trace schematic or starts referencing address/data lines as if those somehow "magically answer the question" is when I get up and leave. In my experience, EE/hardware-focused people tend to give you one-liner answers or links to a schematic and don't really explain anything at the "programming" level.
Again, applying a bit of ego (I've just got out of a work meeting that went so-so, so pardon me for sounding brash): I am living proof that you
DO NOT need to understand EE/hardware to work on video game consoles or embedded systems (I've done PIC, worked a bit with MIPS/ARM systems running Linux), or even other things such as storage subsystems (I love working with ATA protocol on MHDDs or SSDs -- and AHCI too -- for example). I am a very strong proponent/advocate of the fact that clear, concise, and well-written documentation for developers/programmers can alleviate 99% of the "need" of understanding EE/hardware. EE/hardware folks have their own docs that make sense to them, and many of them can understand the documentation that's the "next level up" -- but not all of us can understand EE/hardware documentation.
To be clear: I'm not arguing against bazz or saying "you're wrong" (he's not wrong!). I'm not saying understanding EE/hardware isn't helpful -- bazz is proof it's remarkably helpful, and that's totally awesome! -- but there are those of us who do not really care to get into that arena and prefer to work at the layer immediately above hardware (i.e. firmware and upwards). And for us, the solution is well-written documentation that presents information in such a way that both "newbies" and those familiar/skilled with similar tech can actually understand what's going on. So if you're one of those people like me, please don't feel alone or frustrated. :-)
Clear/concise and well-written documentation by someone who understands "how" to write technical documentation at that level goes a long, long way. A lot of the stuff I've seen on the superfamicom wiki (the technical references, not the howtos) makes me cringe (
recent example), because it's almost like it was written by a single person who was thinking of/for themselves and not about the readers or their skill sets. And please, whoever reads this, don't respond with "it's a wiki, you have the power to fix it yourself" -- yeah, um, considering I already wrote documentation (not perfect but was way better than what we had at the time) of all this back in the 90s, I think that'd be kind of defeatist.
A short story which I feel proves this fact: from 1996 to 1997, I had absolutely no idea how the NES's graphics worked (specifically the attribute table and how it works "with" the pattern table to define colour of a pixel). I tried for almost a year to wrap my brain around it, and it just never "clicked". It wasn't until I had a roommate -- Mr. Snazz, co-author of our VeNES emulator, who also had no hardware background -- who (after he got graphics working) said "really? It's really easy, it's like this"" and explained it in a way that suddenly clicked (I actually jumped around the room with excitement after). And that is why in nestech.txt I wrote my description of the attribute table how I did (describing it in 3 different ways, alongside ASCII diagrams). Almost 20 years later, I still see people struggling with understanding how it works, and have gotten a lot of "oh my god, thank you, that makes so much sense!" notes privately when people got to that description.
Likewise, one of the best write-ups I've seen of the NES nametables and scrolling is this. While things like this begin to make me cringe (but that's also the nature of the PPU, I guess -- it isn't as simple as was once thought).
I could list several other examples of the same -- such as understanding how some of the design/aspects of the Apple II and Apple IIGS, which I got through both the Technical Reference tomes from Apple as well as through conversations with people who would describe stuff in such a way that it just clicked/made sense -- but that's superfluous I think.
koitsu wrote:
Might I respectfully suggest trying it out on an actual SNES?
Did anyone ever check this on SNES? I'm curious what is going on.
Haven't gotten around to it yet. Will try to this weekend. I've added it to my never-ending todo list.
Tried this out today. Compared results on actual console to that of BizHawk 1.11.6 (2016/03/07) ("BSNES Performance"), SNES9x w/ Debugger 1.51ep10r2, no$sns 1.5, and zsnes 1.51.
The results on emulators are all the same: white "5" near the upper left corner.
On an actual console, the white is more like a high-tone grey (so RGB-wise it looks something like $a0a0a0). Taking a picture of this won't help because it's NTSC and hue/brightness/colour etc. on my TV, plus on the camera, is going to affect the visual results. I can tell it's not white, though, because the SD2SNES boot-up screen uses a pitch white font.
So, odds are you do have a quirk/bug in your code which needs to be worked out. It's probably yellow on higan because of the randomisation of registers and memory contents as byuu describes, and it might be high-tone grey on an actual console (for me) because I'm using SD2SNES which obviously has to pre-initialise the SNES in several ways (including palette).
It would be really useful to have a debugger feature that stores a flag to detect when registers/memory is read before being written to after power-on/reset to catch bugs like this. I think people would be stunned by just how often even commercial games do this.
Unfortunately, it seems like that would be a massive amount of work to add "modified" flags to every single register and volatile memory address. And a huge speed penalty to then check these bits every time a memory address is read. Not to mention a cache destroyer.
Memory randomization is the bare minimum I can do, really. The color should change every power cycle if that is indeed what's going on, though.
> In higan-accuracy, however, sometimes the number doesn't show up or shows up with a different color.
EDIT: okay, yeah. I guarantee it's something not being initialized properly. You really need to clear everything: all registers, all WRAM, VRAM, CGRAM, OAM, etc.
Hey, nicklausw, nice to hear you've got started on SNES development.
nicklausw wrote:
As for what to look for, what's supposed to happen in this: in the top left corner of the screen, the number '5' is drawn and is white.
Tried it on the PowerPak, where the number appears as expected, and on sd2snes. With the latter, the number is barely visible and almost looks like an outline (i.e. pixels seem to be missing).
So yeah, like others have pointed out, it's most likely a problem with inadequate system initialization.
OK, I f'n solved it.
This fixes the problem...
I added this just before the infinite loop (before screen on)...
Code:
lda #$30
sta $2130
stz $2131
stz $2132
stz $2133
So, the problem was...I'm an idiot. Higan does NOT reload the rom every time it's run. It keeps a copy of the rom, upon import, but you have to REIMPORT the rom if it is changed. The hour of testing I did the other day was a complete waste of time, because I was testing the exact same original rom over and over, and not the changed rom.
OK. I feel better now. Bright white '5' in Higan Accuracy.
Thanks, dougeff. I managed to 'port' over my message printing function from my NES hello world examples and now a message is printed onto the screen.
Now, my one question...
WHY DO THE NEVIKSTI TUTORIALS MAKE THIS LOOK LIKE SUCH A HUGE TASK!?
Seriously, it's having an init routine clear stuff, then some DMA transfers and setting variables and copying text to VRAM. Why did that tutorial have to be filled with so much bloat? Jeez...
In other news, I've been playing around with xkas-plus and bass (byuu's non-linker assemblers, the first of which forked by Revenant) and have decided that I'll just stick with ca65. They're nice and all, but are very hollow in features compared to other assemblers (even WLA) and the way code is parsed is very weird. I kinda liked bass, but it has no idea how to handle spaces, so.
psycopathicteen wrote:
There's also bass, xkas, and asar, for those who want to be able to move the direct page around.
How so? I can't seem to find this specific functionality in xkas-plus. Do you mean that it lets you subtract the higher bit?
xkas(-plus) doesn't have any specific direct page functionality aside from being able to force 8-bit addresses for instructions that support them.
xkas and bass are both intended mainly for patching existing binaries, so I wouldn't really recommend them for writing anything from scratch (although I still sometimes do so myself out of habit).
I know xkas and bass are better for patches, I'm just playing with the idea of a SNES assembler with no linker phase. I kinda like it. Probably won't be doing any big switches, though.