I'm an idiot (failure to create pong "bouncing" ball)

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.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by Drew Sebastino »

koitsu wrote:You aren't going to need 32mbit, or anywhere close to it, for a pong game.
It definitely wasn't for this. :lol: I'm sick of Pong, I liked my object system because it was easier to keep track of things, but that takes longer to make.
koitsu wrote:Once you accomplish that fully, then you can go back and try something like converting your game from mode 20 to mode 21 as a learning experience.
I have to figure though, there has to be some demo that somebody has made that uses HiROM, right? All I really need is the initialization routine, and although I could try and make it, I'm not going to reinvent the wheel if I don't have to.

Do you think that it would be easier for me to make a full fledged game in LoROM and then convert it to HiROM then to try and convert the initialization routine to HiROM and then make the game because I'd have more experience? I really liked the Splatoon SNES idea. I could even render the character in Blender and draw over them to clean them up for sprites, (be prepared for another topic asking how to actually do this :lol: ) and I've figured out how everything will work from a graphical standpoint.

By the way, when I say HiROM, I really mean Mode 25.

I will admit though, the likelihood of me ever needing over 32Mb of rom is very slim, (I like a lot of graphical variety and frames of animation, but at the rate I draw, I won't ever get that much done) but like I've stated before, I want to make a game engine that I can release publically that could get more people into SNES development. The best day will be when we get people to collaborate in making games here.
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by rainwarrior »

Espozo wrote:I'm sick of Pong.
If you're already sick of Pong, do you really expect to make it through a bigger project?

I've said it elsewhere before, but if you want finished projects, pick projects that you can finish.

If you can't finish pong, make something smaller first. ;)
User avatar
koitsu
Posts: 4203
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by koitsu »

1. There are no demos I know of that use mode 21 or mode 25. Because, again, people don't really care: 32mbit of addressing space is a lot for most homebrew (and most (all?) homebrew I've seen has been mode 20). There are ***very*** few games that used more than 32mbit of space. (Don't let anyone show up here and tell you otherwise -- they are in the tiny minority, like maybe 1 or 2% of all SNES/SFC titles?)

2. You need more than an initialisation routine. You need to understand fully how the memory map works, because you're going to need to know how to organise your code and configure the assembler/linker so that labels/addresses/etc. refer to the proper bank. I've explained it as best I can, tepples has explained it a few times too, and some other folks have as well. I can't speak for others, but I'm at my wit's end trying to explain it.

3. I think you need to make a mode 20 game. I will repeat myself in a way: stop getting hung up on mode 20/21/25/whatever. USE MODE 20. You are absolutely in *no way/shape/form* at a skill level (right now) to be worrying about other memory modes. You just aren't. Nobody goes out and for their very first game, with absolutely no development or programming knowledge prior, creates something like Splatoon. Step back and be realistic. Baby steps (I've said this before). Nothing **at present** is going to stop you from making a mode 20 Splatoon-like game.

I'm sorry if this is harsh, but: the only thing I've seen from you to date is a screen that showed some graphics you ripped off from Metal Slug, converted them to one of the SNES's graphics formats (I don't remember which mode you used), threw in some sprites on top of it, and made joypad input move some sprites around (if I remember right). That's actually a **great** start! You should stick with improving that and doing with it whatever you want. I think overall you spend more time worrying about shit like mode 20/21/25 than you do actually accomplishing whatever your goals are. Turn off that part of your brain (I can tell you this because I myself have some form of OCD and have to turn that part of my brain off at times).

Worry about "running out of ROM space" when you get there. You ain't even close to being there yet with what you've done/got so far. You're trying to wear very "big boy" pants without even wearing pull-ups yet; wearing pull-ups is part of the process, and it's OK! That's me being respectful and realistic combined, k?

And keep in mind: **I** have never done an actual SNES (or NES!) game myself either. I've done lots of modifications and reverse-engineering of existing things, and of course written fresh code (for things like the Demiforce FF2j/FF2e intro), but game engines and actual game development is something I haven't done. Just the thought of it makes me cringe in fear -- it's a HUGE undertaking, even for someone that does have knowledge of the systems. Most of the guys on nesdev know way more than I do, and have accomplished way more than I do. So maybe take what I say with a grain of salt, but I assure you (no ego here) there is wisdom in my words.

4. The terms "LoROM" and "HiROM" have, since I have been doing this (since the very early 90s), always referred to mode 20 and mode 21. Mode 25 is a completely different beast. Please going forward say mode 25 and not HiROM, because the memory map is different for mode 25 than 21.

5. Then go work on your game engine! Do it in mode 20. If there becomes some kind of limit that would be alleviated switching to mode 21 or mode 25, then worry about that when you get there. Once you have that level of skill/knowledge, I think you'll find that (if deemed necessary) migrating your engine to use mode 21 or 25 won't be that hard for you. Trust me.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by Drew Sebastino »

rainwarrior wrote:If you're already sick of Pong, do you really expect to make it through a bigger project?
I just don't know what's going on, and I have a lack of motivation to fix it. Everything just fit so much more nicely with an object routine and a collision routine and whatnot: All I'd need to do is say the metasprite address, the size of the objects and what type of collision needs to be checked, and bam, done, and this is usefull for all types of objects. Instead, I'm writing stuff like:

Code: Select all

lda Paddle1YPosition
sta SpriteBuf+5
clc
adc #$08
sta SpriteBuf+9
clc
adc #$08
adc SpriteBuf+13
clc
adc #$08
adc SpriteBuf+17
Maybe I can make an object routine and all the stuff that goes with it, and then come back to making Pong using it.
rainwarrior wrote:If you can't finish pong, make something smaller first. :wink:
Well, I sort of finished it, it was just buggy and unpolished as all get out. I guess that's a step toward modern game development. :lol:

Anyway, what could I possible make that's more simplistic than Pong? I already got the screen to turn on flawlessly, does that count? :lol:

And yeah, thanks again koitsu for knocking some sense into me. I guess I'll just leave the other topic to die. I got too compulsive and jumped straight ahead. I'm not a fumbling idiot, but I've got a fair share of downsides, many that you are (unfortunately) well aware with.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by tepples »

As far as I can gather based on discussions of Tales of Phantasia, mode $25 is called "ExHiROM" because it shares a lot more with HiROM ($21) than with LoROM ($20).

But I agree with koitsu: If staying in mode $20 helps you learn, do so.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by Drew Sebastino »

How I work when I'm motivated: (I did this in the timespan of a couple of comments ago to now)

Code: Select all

  lda #.BANKBYTE(dummy)
  rep #$30	;A=16, X/Y=16
  sta ObjectTable+Identity
  lda #.LOWORD(dummy)
  sta ObjectTable+Identity+2

;====================================================================================

infinite_loop:
  wai			;Wait for interrupts to finish (NMI/VBlank)

  rep #$30	;A=16, X/Y=16

  jsr start_object_identifier

  rep #$30	;A=16, X/Y=16
  inc ColorCounter
  sep #$20	;A=8
  lda #$00
  sta $2121
  lda ColorCounter
  sta $2122
  lda ColorCounter+1
  sta $2122

  jmp infinite_loop	;Do this forever
.endproc

;====================================================================================
;====================================================================================

.proc start_object_identifier
  rep #$30	; A=16, X/Y=16
  lda #ObjectTable
  sta ObjectTableOffset
  tcd

object_identifier_loop:
  lda Identity				;load the object identification byte of the object we're currently on
  beq next_object
  pha
  sep #$20	;A=8
  lda Identity+2
  pha
  rts
next_object:
  rep #$30	; A=16, X/Y=16
  lda a:ObjectTableOffset		;says how many objects have been identified
  clc
  adc #$0020				;add 24 to look at the next object
  sta a:ObjectTableOffset		;store the result for the next time we go through the loop
  tcd					;transfer the accumulator to y for "cpy #8192" and "lda ObjectTable,y"
  cmp #ObjectTableSize+ObjectTable	;sees if all objects have been identified (each object is 48 bytes)
  bne object_identifier_loop		;if so, quit searching
  lda #$0000
  tcd
  jsr process_oam
  rts

.endproc

;====================================================================================
;====================================================================================

.proc dummy
  rts

.endproc
Basically, it's just a piece of code that looks through an object table, loads the 3 identification bytes which signify the address, pushes them to the stack, and then does an rts to get there, a trick tepples told me he found from a book about the Apple IIGS. (This is better than my old setup, where I used a lookup table that only allowed for 16 bit addresses.)

I can tell it works because I have code that changes the background color every frame that gets run after this, and it works.

Again, thanks for knocking some sense into me, and, of course, putting up with me.

I have to say though, and I know I've already been told this, but how do you create a sort of list that works like ".res", but only for the list and not the entire SNES memory? I want to create one for the object table. Also, I want to have it to where the object table size is automatically calculated based on multiplying the slot size (which should be automatically calculated to equal the list size) times the number of slots. Hopefully, this isn't asking too much. :lol:
psycopathicteen
Posts: 3001
Joined: Wed May 19, 2010 6:12 pm

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by psycopathicteen »

Yeah, I think you were just a bit rusty from putting this off because of school.

Anyway, I have good news for you. I found a way to simplify my animation engine, without noticeable compromises.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by Drew Sebastino »

That's good news. I'm assuming you're still doing the 16x16 and 32x32 searching thing. Did you ever get it to check for redundant tiles?

Anyway, I'm not to happy with myself, because I found a bug that had actually made it work.

I think you can figure out how this is wrong:

Code: Select all

  lda #.BANKBYTE(dummy)
  sta ObjectTable+Identity
  rep #$30	;A=16, X/Y=16
  lda #.LOWORD(dummy)
  sta ObjectTable+Identity+2
So then, I fixed it, and I get a crash:

Code: Select all

  lda #.BANKBYTE(dummy)
  sta ObjectTable+Identity
  rep #$30	;A=16, X/Y=16
  lda #.LOWORD(dummy)
  sta ObjectTable+Identity+1
What's going on in the first example is the number actually ends up being 0, which counts as a negative object, so it skips the part where it tries to do the rts to jump to the code. I found I was only checking to see if the top 16 bits were 0 instead of all 24, so I corrected it, and now even the top example doesn't work, but filling all 24 bits with 0 does.

This has to be the problem, but although I'm starring right at it, I don't see it:

Code: Select all

object_identifier_loop:
  lda Identity
  bne continue_object_identifier_loop
  lda Identity+1
  beq next_object
continue_object_identifier_loop:
  pha
  sep #$20	;A=8
  lda Identity+2
  pha
  rts
next_object:
  rep #$30	; A=16, X/Y=16
User avatar
Ramsis
Posts: 341
Joined: Sun Jul 01, 2012 6:44 am
Location: Lion's den :3
Contact:

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by Ramsis »

Espozo wrote:I think you can figure out how this is wrong:
In fact, the first and the second code snippets are both faulty.

Here's a hint to help you work out the real fix all by yourself:
The bank byte of any given 24-bit address = the highest 8 bits of the address. :wink:
(This is of course assuming that ObjectTable+Identity is indeed supposed to contain a 24-bit address, and that your third fragment of code is bug-free.)
Some of my projects:
Furry RPG!
Unofficial SNES PowerPak firmware
(See my GitHub profile for more)
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by Drew Sebastino »

Ramsis wrote:The bank byte of any given 24-bit address = the highest 8 bits of the address. :wink:
Hmm... I guess this is right then:

Code: Select all

  lda #.BANKBYTE(dummy)
  sta ObjectTable+Identity+2
  rep #$30	;A=16, X/Y=16
  lda #.LOWORD(dummy)
  sta ObjectTable+Identity
Well, unfortunately, I can't get it to work. I guess I'm not pushing the addresses in the correct order? (I tried with the original code, and it didn't work either)

Code: Select all

  rep #$30	; A=16, X/Y=16
object_identifier_loop:
  lda Identity
  bne continue_object_identifier_loop
  lda Identity+1
  beq next_object
  lda Identity
continue_object_identifier_loop:
  pha
  sep #$20	;A=8
  lda Identity+2
  pha
  rts
next_object:
  rep #$30	; A=16, X/Y=16
Should I instead be pushing from 3-1 instead of 1-3? I can't think right now. :(
User avatar
Ramsis
Posts: 341
Joined: Sun Jul 01, 2012 6:44 am
Location: Lion's den :3
Contact:

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by Ramsis »

I really can't tell what's wrong with your routine from those code snippets, but this looks fishy:
Espozo wrote:

Code: Select all

  lda Identity+2
  pha
  rts
Remember that rts pulls 16 bit of data (namely, a return address minus 1) off the stack. So if you push some random data immediately before, unexpected behavior (i.e., a program crash) is the unavoidable consequence. :wink:
Some of my projects:
Furry RPG!
Unofficial SNES PowerPak firmware
(See my GitHub profile for more)
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by Drew Sebastino »

Ramsis wrote:Remember that rts pulls 16 bit of data
Oh... :( I thought it did 24: I did a 16 bit pha followed by an 8 bit pha, which I thought rts would cancel it, but I realize I need to use rtl.

I just tested it, but it unfortunately doesn't work, and I also changed the rts in "dummy" to rtl. I might just give up on trying to make this a long jump, but I'm kind of doubtful I can fit all the object program code I want in one bank.

Actually, I just thought of something... I'm sending the location of where I want to go to the stack, pulling it, and then on the next rtl, I'm actually pulling more than I'm pushing (and I'm not pulling the return address), which isn't good. So, hopefully, if I push the address of the object identifier code loop first, it should work.
psycopathicteen
Posts: 3001
Joined: Wed May 19, 2010 6:12 pm

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by psycopathicteen »

There is a long indirect jump instruction.

Code: Select all

 rep #$30   ; A=16, X/Y=16
object_identifier_loop:
  lda Identity
  sta temp_address
  bne continue_object_identifier_loop
  lda Identity+1
  beq next_object
continue_object_identifier_loop:
  lda Identity+1
  sta temp_address+1
  jmp [temp_address]
next_object:
  rep #$30   ; A=16, X/Y=16
That's good news. I'm assuming you're still doing the 16x16 and 32x32 searching thing. Did you ever get it to check for redundant tiles?
No, but I found an easy way to make duplicated sprites when necessary.

So basically, my simplified slot searching algorithm works like this. At start up it copies a list of 20 32x32 slot CHR numbers, and a list of 32 16x16 slot CHR numbers. When it needs to a 32x32 slot, it pulls a number off the top of the list, and pushes it back on when it's done. The same with 16x16 slots.

Grabs a slot CHR number:

Code: Select all

ldx {large_slot_stack_index}
dex
dex
lda {large_slot_stack},x
stx {large_slot_stack_index}
Clears the slot:

Code: Select all

ldx {large_slot_stack_index}
sta {large_slot_stack},x
inx
inx
stx {large_slot_stack_index}
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by Drew Sebastino »

I did what you're saying, and I know I can't do an RTL anymore, so I wrote:

Code: Select all

.proc dummy
  jml object_identifier_loop
And it's telling me that "object_identifier_loop" is undefined, except it definitely isn't, and the code even comes after "object_identifier_loop" in the file, so I don't know what's up with the assembler.

You know, does this actually give me any advantage over what I tried earlier? It only wouldn't work because of the RTL in "dummy", but I can't do it here either.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: I'm an idiot (failure to create pong "bouncing" ball)

Post by tokumaru »

IIRC, ca65 does this because it assumes you're going to define that label later, within the same scope it's being referenced, but then you don't, so an error occurs.

If that label is global, you can do jml ::object_identifier_loop, if it isn't, use the name of its scope. Working with scopes in ca65 (.proc creates a new scope) can be tricky sometimes.
Post Reply