SNES Splatoon (How do I shot HiROM?)

Discussion of hardware and software development for Super NES and Super Famicom.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
psycopathicteen
Posts: 3001
Joined: Wed May 19, 2010 6:12 pm

Re: SNES Splatoon (How do I shot HiROM?)

Post by psycopathicteen »

What was wrong with his avatar?

I wonder why there's all this fuss about ca65? Byuu has a very nice assembler on his website, it has none of that segment crap on it. It's pretty much tell the assembler what kind of ROM it is, and what CPU address to start the code at, and that's all.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: SNES Splatoon (How do I shot HiROM?)

Post by Drew Sebastino »

User avatar
Ramsis
Posts: 341
Joined: Sun Jul 01, 2012 6:44 am
Location: Lion's den :3
Contact:

Re: SNES Splatoon (How do I shot HiROM?)

Post by Ramsis »

koitsu wrote:Otherwise you have some code that's stomping all over RAM contents (I peeked at the memory contents at one point -- they become a giant mess, usually filled with a lot of zeros), and it's not my job to figure out why. :-)
His Vblank routine is messed up:

Code: Select all

.proc VBlank
  rep #$30	;A=16, X/Y=16
  pha
  phx
  phy
  phd
  phb
  php
  lda #$0000
  tcd

----------------------- snip -----------------------

  jsr get_input	;update joypad data

  lda $4210	;clear NMI Flag

  plp
  plb
  pld
  ply
  plx
  pla
  rti
.endproc
It pushes a 16-bit value for A, but it only pulls back an 8-bit value. (The get_input subroutine does a php / plp, so when it returns from that routine, A is still 8-bit.) That means that the stack pointer decreases by (at least) one 60 times per second, hence the data mess in RAM. Edit: My mistake, it should indeed pull 16-bit values back, thanks to the plp. Not exactly the most obvious/elegant way to do it, IMHO.

Also worth noting is that the php / plp combo in the Vblank routine is completely useless (Edit: though not in this particular case actually, see above), as the processor status gets pushed onto the stack automatically as soon as NMI fires, and rti pulls it back along with K and PC. Also, the php occurring after the initial rep #$30 doesn't make any sense at all. (Using php, you'll want to preserve an unchanged processor status and therefore not mess with rep / sep beforehand.)

Anyway, the bug must be lurking elsewhere in the code. :wink:
Some of my projects:
Furry RPG!
Unofficial SNES PowerPak firmware
(See my GitHub profile for more)
Kannagi
Posts: 100
Joined: Sun May 11, 2014 8:36 am
Location: France

Re: SNES Splatoon (How do I shot HiROM?)

Post by Kannagi »

Besides, I have a question, I see many people do pha / pla phx / plx during VBlank, I know what it is I use the Stack but is it really necessary for VBlank?
I mean, normally you don't execute code before calling the Vlank (unless you make a wai) or you made a loop to wait VBlank?
lint
Posts: 25
Joined: Thu May 15, 2008 4:05 am

Re: SNES Splatoon (How do I shot HiROM?)

Post by lint »

Well, you can wait for the VBlank ... But the VBlank can also occurs when you execute code in your main loop. You never know ... ;)
https://twitter.com/Lint_
http://snesdev.antihero.org/ [depecated blog, new one coming one of these days]
Kannagi
Posts: 100
Joined: Sun May 11, 2014 8:36 am
Location: France

Re: SNES Splatoon (How do I shot HiROM?)

Post by Kannagi »

I understand, but In general I always look at the CPU , so my code is done fast enough before the VBlank activates. :)
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: SNES Splatoon (How do I shot HiROM?)

Post by tepples »

Kannagi wrote:I understand, but In general I always look at the CPU , so my code is done fast enough before the VBlank activates. :)
Can you guarantee that, even in a worst-case slowdown situation? It's only about a dozen or so cycles.
Kannagi
Posts: 100
Joined: Sun May 11, 2014 8:36 am
Location: France

Re: SNES Splatoon (How do I shot HiROM?)

Post by Kannagi »

Just don't be at 90% CPU (it is a good exercise).
After this depends on if it is true that my game loop is too long may be that I will reflect to a push / pop ( I worked first on the optimization).
psycopathicteen
Posts: 3001
Joined: Wed May 19, 2010 6:12 pm

Re: SNES Splatoon (How do I shot HiROM?)

Post by psycopathicteen »

You could disable the interrupts and re-enable it at the end of the frame, just to be on the safe side. You might get a black bar at the top from entering vblank late on busy frames, but it's still a lot more stable than interrupting an unfinished frame.

Too bad I can't do this because I run software sprite rotation code while it's waiting for vblank. I think I used to do this way, actually.
User avatar
koitsu
Posts: 4203
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: SNES Splatoon (How do I shot HiROM?)

Post by koitsu »

Kannagi wrote:Besides, I have a question, I see many people do pha / pla phx / plx during VBlank, I know what it is I use the Stack but is it really necessary for VBlank?
I mean, normally you don't execute code before calling the Vlank (unless you make a wai) or you made a loop to wait VBlank?
Yes, it is necessary. Think about this situation:

VBlank routine (and is tied to NMI) does this

Code: Select all

  lda #$1234
  rti
Main code (outside of VBlank):

Code: Select all

  lda #$4444
  sta $2122
Now tell me what gets written to $2122 when NMI fires between the two instructions in the main code. :-) Use of wai etc. doesn't change this situation. Henceforth, pushing A/X/Y/B/D/P and pulling P/D/B/Y/X/A is an extremely standard/common operation in interrupt routines.
Kannagi
Posts: 100
Joined: Sun May 11, 2014 8:36 am
Location: France

Re: SNES Splatoon (How do I shot HiROM?)

Post by Kannagi »

I don't really understand your example but in my code $2122 is $44
(But $ 2122 must be written in the VBlank normally).

I changed the code a bit I did this:

Game loop :

Code: Select all

		lda $00
		sta 2121
		rep #$20
		lda #$4444
		sta $2122
		sep #$20
               ;code game
VBlank :

Code: Select all

       ;code
	rep #$20
	lda #$1234
	sep #$20
	rti
And I didn't see change.
User avatar
Ramsis
Posts: 341
Joined: Sun Jul 01, 2012 6:44 am
Location: Lion's den :3
Contact:

Re: SNES Splatoon (How do I shot HiROM?)

Post by Ramsis »

Kannagi wrote:I don't really understand your example but in my code $2122 is $44
(But $ 2122 must be written in the VBlank normally).
The whole point is: If NMI should fire right in between the two instructions in the main code, then an immediate value (i.e., the number) of $1234 gets written to the destination (whatever that may be) instead of the intended immediate value of $4444.
Some of my projects:
Furry RPG!
Unofficial SNES PowerPak firmware
(See my GitHub profile for more)
User avatar
koitsu
Posts: 4203
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: SNES Splatoon (How do I shot HiROM?)

Post by koitsu »

What Ramsis said. In other words: I don't think you understand the fact that NMI can actually happen at any time (it's tied to VBlank in most cases, so you can "sort of" know when it's going to happen, but not definitively -- hence tepples asking the question).

When an interrupt occurs, the contents of all registers aren't saved or restored automatically. So in the example I gave, think about what happens. This is LITERALLY what goes on within the processor:

Code: Select all

Main: lda #$1234    ; A=$1234
{NMI begins}
NMI: lda #$4444     ; A=$4444
NMI: rti
{NMI ends}
Main: sta $2122     ; $4444 is written to $2122
Now, if you save/restore the accumulator in your NMI routine, all is fine:

Code: Select all

Main: lda #$1234    ; A=$1234
{NMI begins}
NMI: pha
NMI: lda #$4444     ; A=$4444
NMI: pla            ; A=$1234
NMI: rti
{NMI ends}
Main: sta $2122     ; $1234 is written to $2122
So, to recap: "is saving/restoring all the registers in an interrupt routine really needed?" The answer is YES.

I'm well aware that on 65816 you can use wai to pause/wait for NMI (VBlank) to end, but there's going to come a time where you've got code running in a main (non-VBlank) loop and NMI kicks in, and suddenly all your registers change for a reason not immediately apparent. So if your NMI routine uses A/X/Y registers, tweaks B, and/or changes register sizes, then you absolutely need to push A/X/Y/B/P and restore those before doing the rti, otherwise once returning control to your main loop (non-VBlank), previous register contents are trashed.
Kannagi
Posts: 100
Joined: Sun May 11, 2014 8:36 am
Location: France

Re: SNES Splatoon (How do I shot HiROM?)

Post by Kannagi »

Yes I understand, the VBlank, it can occur at any time?
Normally it does not come at the end of the final line ?
There is an example or VBlank comes before?
psycopathicteen
Posts: 3001
Joined: Wed May 19, 2010 6:12 pm

Re: SNES Splatoon (How do I shot HiROM?)

Post by psycopathicteen »

When does it NMI besides vblank?
Post Reply