SNES dev newbie questions
Moderator: Moderators
Forum rules
- For making cartridges of your Super NES games, see Reproduction.
Re: SNES dev newbie questions
If you can think of a good place to split it, send me a PM.
Re: SNES dev newbie questions
Well, most of the questions I have been asking were about SNES initalisation, so perhaps the topic should simply be renamed. I can't say I understand all of this, but I haven't studied how DMA works at all yet. Thanks everyone for contributing to the discussion, I am learning a lot.
-
- Posts: 183
- Joined: Tue Apr 05, 2005 7:30 pm
Re: SNES dev newbie questions
The paragraph is saying "don't attempt to do general DMA from WRAM to WRAM." That includes the mirrored sections in banks $00-$3f and the WRAM banks $7e and $7f. In order to use general DMA to clear WRAM, you would have to store a zero value in the ROM itself somewhere (or possibly external RAM) and have the general DMA use that as the A-bus fixed source.koitsu wrote: I've read this paragraph 4 times now, and it's bloody confusing. I can't reliably say I understand what it means, specifically the phrases "attempting a DMA from WRAM to this register" and "attempting a DMA from this register to WRAM". The only conclusion I've been able to reach is that the author of those lines is trying to say "Don't use general DMA to read from banks $7e/7f + write to $2180, and don't use general DMA to read from $2180 + write to banks $7e/7f", and if that's the case, then I can see some legitimacy in that.
But neither case is what my code was doing. The code uses general DMA to read from $000000 (fixed address) and writes to $2180. I'm aware of the RAM mirroring (banks $00-3f, ranges $0000-1fff, from banks $7e/7f). If what you're saying is that the above code won't work, then that brings into question byuu's statement that general DMA can be used to clear WRAM.
It's really good that we're discussing all this and probably confusing the hell out of the OP. *rolls eyes*
I'm with whoever wants to split this discussion into another thread, by the way.
Be whatever the situation demands.
Re: SNES dev newbie questions
doppleganger is correct.
The original quote is just a more verbose way of saying WRAM A <> WRAM B does not work, regardless of DMA transfer direction. Think about it from a hardware perspective: how can the same chip with one address+data bus be read from and written to at the same time at different locations?
So use an A-bus address ($43x2-4) that is not WRAM (nor a mirror of it.) ROM is the surefire method, but you could also do SRAM if you have some.
The original quote is just a more verbose way of saying WRAM A <> WRAM B does not work, regardless of DMA transfer direction. Think about it from a hardware perspective: how can the same chip with one address+data bus be read from and written to at the same time at different locations?
So use an A-bus address ($43x2-4) that is not WRAM (nor a mirror of it.) ROM is the surefire method, but you could also do SRAM if you have some.
Re: SNES dev newbie questions
Do otherwise unused DMA registers work as a readable A-bus address for this?
Re: SNES dev newbie questions
Okay, then that also means the ClearVRAM routine written by Neviksti is wrong as well. *shakes head* So much broken code...
I'm going to generally bow out of assisting at this point. The reason has to do with the fact that all of this quickly becomes assembler-focused (meaning the code written has more and more of a dependency and requirement relating to the assembler being used and its related syntax requirements), and since I don't know WLA and find its documentation a bit of a mess, I choose to opt out. :D
The information being provided here is great/fantastic, however.
I'm going to generally bow out of assisting at this point. The reason has to do with the fact that all of this quickly becomes assembler-focused (meaning the code written has more and more of a dependency and requirement relating to the assembler being used and its related syntax requirements), and since I don't know WLA and find its documentation a bit of a mess, I choose to opt out. :D
The information being provided here is great/fantastic, however.
Re: SNES dev newbie questions
> Do otherwise unused DMA registers work as a readable A-bus address for this?
No, $21xx, $40xx, $41xx, $42xx, $43xx don't work. You either get open bus or 0x00 (depending on register and model) when you specify them as the A-bus address.
I don't even want to imagine how much "fun" you could have DMA'ing data directly to $420b (DMA enable)
> Okay, then that also means the ClearVRAM routine written by Neviksti is wrong as well.
ClearVRAM should work fine. It's transferring from WRAM to VRAM.
The problem is only with going from WRAM to WRAM.
> and since I don't know WLA and find its documentation a bit of a mess, I choose to opt out. :D
Unfortunately we can't all agree to use the same assembler. Even when we make our own, we often want to improve it and remove past mistakes. All I can recommend for writing truly portable code is to stick to straight opcodes and labels:
"lda #$00", "lda #$ffff" (no .b, .w), "label:" (no -/+, no .label, etc.)
Skip the macros, the directives, the defines, etc.
No, $21xx, $40xx, $41xx, $42xx, $43xx don't work. You either get open bus or 0x00 (depending on register and model) when you specify them as the A-bus address.
I don't even want to imagine how much "fun" you could have DMA'ing data directly to $420b (DMA enable)
> Okay, then that also means the ClearVRAM routine written by Neviksti is wrong as well.
ClearVRAM should work fine. It's transferring from WRAM to VRAM.
The problem is only with going from WRAM to WRAM.
> and since I don't know WLA and find its documentation a bit of a mess, I choose to opt out. :D
Unfortunately we can't all agree to use the same assembler. Even when we make our own, we often want to improve it and remove past mistakes. All I can recommend for writing truly portable code is to stick to straight opcodes and labels:
"lda #$00", "lda #$ffff" (no .b, .w), "label:" (no -/+, no .label, etc.)
Skip the macros, the directives, the defines, etc.
Re: SNES dev newbie questions
Thanks to everyone, I'm finally feeling like I'm getting things done! If anyone's curious, here's what I have so far:
- MSU1 detection: screen turns green if MSU1 hardware is available, red otherwise. Includes the manifest and XML files to use with your favorite emulator or hardware MSU1 implementation.
- Seizure trigger: WARNING, color changes every frame, epileptics beware!
Code: Select all
lda #$80 ; Bit 7 of $4200 must be set to enable NMI...
sta $4200
sep #%00110000 ; Set the A, X/Y registers to 8-bit.
lda #%00001111 ; Full brightness
sta $2100
wai
; Define color addresses so I don't mess up
.define GREEN $0000
.define RED $0001
.define BLUE $0002
.define NEXTCOLOR $0003 ; 0 = GREEN, 1 = RED, 2 = BLUE
; Set all colors to half intensity at first (because why not)
lda #%00010000
sta RED
sta BLUE
sta GREEN
Forever:
stz $2121 ; We'll want BG0 only
IncNextColor: ; One color is updated per frame, find out which out for this iteration
inc NEXTCOLOR
lda NEXTCOLOR
and #%00000011 ; This is a weird way I thought about to keep looping between 0 through 2
sta NEXTCOLOR
cmp #%00000011
beq IncNextColor
cmp #$00
beq Update_Green
cmp #$01
beq Update_Red
cmp #$02
beq Update_Blue
; The following blocks increment the colors by 1, 2 and 3 respectively
Update_Green: ; low: #%11100000, high: #%00000011
lda GREEN
adc #%00000001
and #%00011111 ; so that it's never above 31
sta GREEN
jmp Update_Color
Update_Red: ; low: #%00011111, high: #%00000000
lda RED
adc #%00000010
and #%00011111
sta RED
jmp Update_Color
Update_Blue: ; low: #%00000000, high: #%01111100
lda BLUE
adc #%00000011
and #%00011111
sta BLUE
jmp Update_Color
Update_Color: ; let's "build" the full color bytes
lda GREEN
asl a
asl a
asl a
asl a
asl a
adc RED
sta $2122 ; low byte (#%GGGRRRRR)
lda GREEN
lsr a
lsr a
lsr a
ror a
ror a
adc BLUE
rol a
rol a
sta $2122 ; high byte (#%0BBBBBGG)
wai
jmp Forever
Re: SNES dev newbie questions
I think you're missing clc before your adc statements.
Re: SNES dev newbie questions
Indeed! Thank you.
Re: SNES dev newbie questions
Quoted from this topic:
Other unrelated question: for another project, I used functions from this document by blargg to make sure the SNES DSP isn't muted. Since this is the only single thing I am interested in doing with the DSP right now, I was wondering if I overlooked a faster way to do this? It's not too bad, but it seems to me it's still a lot just to make sure a bit isn't set.
Thank you for reading!
I successfully managed to get SMW playing PCM audio tracks with MSU1, but that was with the help from this document. I did try to trace writes to $214x beforehand, but there sure were a lot of those. Typically, how does one find out where the "play track" function is located? Or more generally, how does one discriminate "interesting" writes to $214x versus the others which do something else?byuu wrote:It takes about 20 minutes to patch a game to use CD-audio: trace out writes to $214x, walk up the stack until you find it loading a track# and calling the "play track" function (every game I've looked at had one), and modify that routine to test if MSU1 is present. If so, play with MSU1. If not, call original function so the game still works just with the regular audio.
Other unrelated question: for another project, I used functions from this document by blargg to make sure the SNES DSP isn't muted. Since this is the only single thing I am interested in doing with the DSP right now, I was wondering if I overlooked a faster way to do this? It's not too bad, but it seems to me it's still a lot just to make sure a bit isn't set.
Thank you for reading!
Re: SNES dev newbie questions
Quick question about rotating bits in accumulator: in the following, I was expecting the 8-bit accumulator to become $80 after the final ROR, but it seems like the set bit just disappeared. This is the bottom code of this post.
I understand that the carry flag becomes set, but I truly hoped for the bit to go around. What am I missing?
Code: Select all
$00/81EF AD 00 00 LDA $0000 [$00:0000] A:0000 X:0000 Y:0000 P:envMXdiZc
$00/81F2 4A LSR A A:0010 X:0000 Y:0000 P:envMXdizc
$00/81F3 4A LSR A A:0008 X:0000 Y:0000 P:envMXdizc
$00/81F4 4A LSR A A:0004 X:0000 Y:0000 P:envMXdizc
$00/81F5 6A ROR A A:0002 X:0000 Y:0000 P:envMXdizc
$00/81F6 6A ROR A A:0001 X:0000 Y:0000 P:envMXdizc
$00/81F7 2A ..... A:0000 X:0000 Y:0000 P:envMXdiZC
- Jarhmander
- Formerly ~J-@D!~
- Posts: 570
- Joined: Sun Mar 12, 2006 12:36 am
- Location: Rive nord de Montréal
Re: SNES dev newbie questions
The result is correct. Think of the rotate instructions as "rotate operand and carry": if A is 8-bit, ROL/ROR rotate through 9 bits, A and carry. That means it requires 9 successive ROLs/RORs to get in A the original value, not 8. That's because the vacant bit gets the carry THEN the carry get the shifted-out bit. Example:
Code: Select all
lda #2 ; assume A is 8 bits.
clc ; A = $02, C = 0
ror a ; A = $01, C = 0
ror a ; A = $00, C = 1
ror a ; A = $80, C = 0
((λ (x) (x x)) (λ (x) (x x)))
Re: SNES dev newbie questions
This makes perfect sense, thank you. The assembly tutorial I read didn't mention this, but then again it wasn't for 65816...
Re: SNES dev newbie questions
In this case what's being described applies to 6502 and 65c02 as well. There is nothing different about ROR/ROL on the 65816 compared to the 6502/65c02.juef wrote:This makes perfect sense, thank you. The assembly tutorial I read didn't mention this, but then again it wasn't for 65816...