The awkward stage between beginner and intermediate

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

User avatar
booker
Posts: 10
Joined: Sun Jul 31, 2011 11:53 am
Location: Canada

The awkward stage between beginner and intermediate

Post by booker »

Alt. Title: How the hell do I even start making a text box?

So I'm sort of new to NES development, but I just can't figure out how to structure my programs. I am not a complete newbie; I've coded something a bit more elaborate than a simple Hello, World! program. But after that, I'm a bit lost. Sure, I've read a lot of material on NES development so far (including borrowing some code from various nesdev places, like tokumaro's ASM6 template), but yeah...

What are the patterns used to structure code for games, programs and demos? How do I switch from controlling a character, making a text box, scripting cutscenes and all that fun stuff? Could someone point me to the intermediate tutorials on this stuff?

Sorry for the numerous questions. I've just kind of reached a roadblock in my epic quest of NES development.
User avatar
Hamtaro126
Posts: 786
Joined: Thu Jan 19, 2006 5:08 pm

Re: The awkward stage between beginner and intermediate

Post by Hamtaro126 »

booker wrote:Alt. Title: How the hell do I even start making a text box?

So I'm sort of new to NES development, but I just can't figure out how to structure my programs. I am not a complete newbie; I've coded something a bit more elaborate than a simple Hello, World! program. But after that, I'm a bit lost. Sure, I've read a lot of material on NES development so far (including borrowing some code from various nesdev places, like tokumaro's ASM6 template), but yeah...

What are the patterns used to structure code for games, programs and demos? How do I switch from controlling a character, making a text box, scripting cutscenes and all that fun stuff? Could someone point me to the intermediate tutorials on this stuff?

Sorry for the numerous questions. I've just kind of reached a roadblock in my epic quest of NES development.
Try looking at the NESDEV Wiki, under Jump Table or RTS trick. Then look at SMBDIS from Romhacking.Net
AKA SmilyMZX/AtariHacker.
User avatar
booker
Posts: 10
Joined: Sun Jul 31, 2011 11:53 am
Location: Canada

Post by booker »

Thanks. I've actually got the RTS/Jump trick implemented in that ROM.

I suppose the way to do it is to have multiple gameloops and then have a pointer to each one. Then, at the end have a

Code: Select all

jmp (gameloopPointer)
and just switch the pointer between modes. Am I on the right track?
User avatar
never-obsolete
Posts: 403
Joined: Wed Sep 07, 2005 9:55 am
Location: Phoenix, AZ
Contact:

Post by never-obsolete »

There are many ways to do it, but here's a quick breakdown of how I structure my code (this is from a LoZ type game I'm working on):

I tend to keep my main states (states that are not really related to each other) separate and use absolute JMP/JSR to get there. "RESET" actually falls into "Sub_TitleScreen" and then into "Sub_MainMenu," but they could be jumped to from anywhere in the code. The name entry screen is contained within "Sub_NewGame."

Code: Select all

RESET:
	; init hardware, variables

Sub_TitleScreen:

	; reset variables
	; do title screen stuff
	; loop until player presses start

Sub_MainMenu:

	; do menu stuff
	; loop untill player makes a choice
	if ( choice == 0 )
		jsr Sub_NewGame
	else
		jsr Sub_LoadGame
	jsr Sub_GameplayMain
	jmp Sub_TitleScreen

This is my main(), and also where I start breaking things down into gamestates and use jmp ($n).

Code: Select all

Sub_GameplayMain:

	; init gamestate

_loop_gameplayMain:
	; check player->actor collsion
	; run actor ai
	; scroll camera if needed
	; check area transition
	; run map script
	; fill oam

	lda #TRUE
	sta frameFinished
_loop_wait:
	lda frameFinished
	bne _loop_wait
	jmp _loop_gameplayMain
	
_loop_exit:
	; death scene or game ending
	rts
frameFinished is cleared in the NMI handler after the vram buffer has been written and sprite dma is finished.


Moving actors (players, enemies, etc) is done in "run actor ai." Text boxes are a substate of the player. The reason for choosing to structure it that way was because the player should not be able to do anything but acknowledge the text box when it's on screen. This may not work for your design, I know there are some RPGs that let you walk around while being talked to. This is how I handle the state of actors:

Code: Select all

	ldy Object_Type, X		 ;
	lda objAI_ptrlo, Y		 ;   get pointer to object
	sta t0					    ;   state table
	lda objAI_ptrhi, Y		 ;
	sta t0 + 1					;
	lda Object_State, X		;   get object state pointer
	asl						    ;
	tay						    ;
	lda (t0), Y				  ;
	sta IndJump			     ;
	iny						    ;
	lda (t0), Y				  ;
	sta IndJump + 1			 ;
	jsr Func_IndirectJump		;   goto ai handler

Code: Select all

Func_IndirectJump:	jmp (IndJump)
Scripting of any kind is handled in "run map script." A pointer is set when an area is loaded and is jumped to every frame.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: The awkward stage between beginner and intermediate

Post by tokumaru »

booker wrote:How do I switch from controlling a character, making a text box, scripting cutscenes and all that fun stuff?
Each section of your game should have an initialization block followed by a loop (sections that are similar enough could share the code though). Each of these sections should have this basic structure:

Code: Select all

1. initialize the game section;
2. read the controllers;
3. update the game world;
4. wait for the vertical blank;
5. update the video;
6. update the audio;
7. go back to step 2;
The part that varies greatly is updating the game world, because the tasks you would perform during a menu are very different than those you'd perform during action gameplay. You just have to do whatever you need to make your game world move one step/frame forward. During this process you'll also have to buffer video information (such as sprite data and background data) that will be written to VRAM during the next vertical blank.

Common tasks such as reading the controllers, clearing sprites, etc. can be put into subroutines, so that they are easily accessible from any part of your game.

The last part (audio and video updates) can be shared among all the game sections if you want to. If you consistently use a standardized buffer system that satisfies all parts of the game you can utilize it for the whole program.

To move from one game section to another, just jump between them. You can JSR to a new section (which will actually be a sub-section) if you plan to return later (something you would do with an in-game menu, for example) or just JMP to it (like when you die and go back to the title screen). You can use jump tables (and the RTS trick) to navigate between game sections too.
User avatar
booker
Posts: 10
Joined: Sun Jul 31, 2011 11:53 am
Location: Canada

Re: The awkward stage between beginner and intermediate

Post by booker »

tokumaru wrote:If you consistently use a standardized buffer system that satisfies all parts of the game you can utilize it for the whole program.
I implemented a really weird system that's really inflexible for this. I was wondering if you have any designs for such a system. The new one I'm working on is like a queue that takes up the entire $0300 RAM page. In it, you load the PPU address hibyte and lobyte, amount of tiles, and then the actual tile data. At VBlank, the address is copied, the tiles are read and copied, until there are no more chunks like these to copy. I was wondering if there is a better method than this.
User avatar
Hamtaro126
Posts: 786
Joined: Thu Jan 19, 2006 5:08 pm

Re: The awkward stage between beginner and intermediate

Post by Hamtaro126 »

booker wrote:
tokumaru wrote:If you consistently use a standardized buffer system that satisfies all parts of the game you can utilize it for the whole program.
I implemented a really weird system that's really inflexible for this. I was wondering if you have any designs for such a system. The new one I'm working on is like a queue that takes up the entire $0300 RAM page. In it, you load the PPU address hibyte and lobyte, amount of tiles, and then the actual tile data. At VBlank, the address is copied, the tiles are read and copied, until there are no more chunks like these to copy. I was wondering if there is a better method than this.
What about using a new mapper with MMC1 or MMC3, put the ram address from the routine as RAM $6x00-6xFF or such, and keep $300-$3FF free.
AKA SmilyMZX/AtariHacker.
User avatar
Memblers
Site Admin
Posts: 3902
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Re: The awkward stage between beginner and intermediate

Post by Memblers »

booker wrote:
tokumaru wrote:If you consistently use a standardized buffer system that satisfies all parts of the game you can utilize it for the whole program.
I implemented a really weird system that's really inflexible for this. I was wondering if you have any designs for such a system. The new one I'm working on is like a queue that takes up the entire $0300 RAM page. In it, you load the PPU address hibyte and lobyte, amount of tiles, and then the actual tile data. At VBlank, the address is copied, the tiles are read and copied, until there are no more chunks like these to copy. I was wondering if there is a better method than this.
That's the way to go I think, as long as it never takes longer than vblank. And make sure your buffer stuffer code is safe to be interrupted by NMI, in case that can happen. If you use this for nametables also, you will want to have the 'VRAM address inc-by-32' feature available for drawing columns. There's a lot of ways to optimize the buffer-unloading code, but it probably only matters if you're wanting to rewrite tiles during vblank (16 bytes per tile adds up fast).

In my NMI routine, I normally rewrite the palette every vblank, copying from RAM. I've found that it makes palette cycling easy to do.
User avatar
Hamtaro126
Posts: 786
Joined: Thu Jan 19, 2006 5:08 pm

Post by Hamtaro126 »

MMC5 seems to be a great mapper for your text routine, Just re-implent it in ExRAM and enable the ExAttribute mode for it! Saves you some space in both RAM areas too,

Or you can use the option that I said before, No big deal.

Memblers: I have to really agree with you, His implentation is really good. I may even use that system somehow. Credit goes to him, though, if I use this ASM file or modify it.
AKA SmilyMZX/AtariHacker.
User avatar
thefox
Posts: 3139
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Re: The awkward stage between beginner and intermediate

Post by thefox »

booker wrote:I was wondering if you have any designs for such a system. The new one I'm working on is like a queue that takes up the entire $0300 RAM page. In it, you load the PPU address hibyte and lobyte, amount of tiles, and then the actual tile data. At VBlank, the address is copied, the tiles are read and copied, until there are no more chunks like these to copy. I was wondering if there is a better method than this.
Yeah this is pretty much the standard thing to do.

One trick is to place the buffer on the lower part of the stack memory area ($100-$1EF or something, depending on how big a buffer/how much stack space you need), since most of the time the stack doesn't grow very big. Then you can also use PLA/PHA to pull/push stuff to/from the buffer.

Also remember that since the PPU address is only 14 bits, you can use the top two bits for stuff like the inc1/inc32 flag. 12 bits is enough if you only need nametable addresses.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: The awkward stage between beginner and intermediate

Post by tokumaru »

booker wrote:I was wondering if you have any designs for such a system.
Like others have said, your way is the most straightforward. I often have a bunch of custom code for this, because I'm a little more ambitious with the amount of bytes I transfer to VRAM than most people, so I really need a few unrolled loops.

One advice I have though is that you allow the program to pick different VBlank handlers. In my game, the main gameplay needs the specialized code I mentioned earlier, but the rest of the program can do with a standard handler, so I just switch as needed.
User avatar
booker
Posts: 10
Joined: Sun Jul 31, 2011 11:53 am
Location: Canada

Post by booker »

Great advice in this thread. Thanks, everybody!
Hamtaro126 wrote:MMC5 seems to be a great mapper for your text routine, Just re-implent it in ExRAM and enable the ExAttribute mode for it! Saves you some space in both RAM areas too,
But isn't MMC5 a rare mapper? If ever I wanted to convert my ROM into an actual cart, that would be difficult. Not that I really think I'll do many ROM to cart conversions, but it is a consideration. Apparently it doesn't even work on the PowerPak!
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

Sane homebrewers will avoid the MMC5. The PowerPak doesn't have an MMC5 implementation, few games used it, it hasn't been cloned by the community, it doesn't work on clone systems... The list of disadvantages is endless.

I don't know why Hamtaro126 brought mappers to this discussion, that just needlessly complicates things and doesn't have anything to do with the original question.
User avatar
Hamtaro126
Posts: 786
Joined: Thu Jan 19, 2006 5:08 pm

Post by Hamtaro126 »

tokumaru wrote:Sane homebrewers will avoid the MMC5. The PowerPak doesn't have an MMC5 implementation, few games used it, it hasn't been cloned by the community, it doesn't work on clone systems... The list of disadvantages is endless.

I don't know why Hamtaro126 brought mappers to this discussion, that just needlessly complicates things and doesn't have anything to do with the original question.
Sorry, Someone else thought of the term ''Takes a lot of RAM'' before me, so I'd thought it would help, but it did not.
AKA SmilyMZX/AtariHacker.
User avatar
MottZilla
Posts: 2835
Joined: Wed Dec 06, 2006 8:18 pm

Post by MottZilla »

Adding 8K of PRGRAM at $6000 makes more sense if you need more RAM than to use MMC5 to get a fraction of that with EXRAM.
Post Reply