Page 5 of 7

Re: NES Programming Blog

Posted: Sun Mar 06, 2016 2:23 am
by Diskover
dougeff wrote:Without the source code, I won't be able to figure it out. Clearly, 2 incorrect spites are appearing.

Have the linker make a label file. Find the address of the label that handles sprites. Set a breakpoint in the FCEUX for execution at that address (at the same time it happens). Step through the code, and see what numbers are being loaded to the Sprite area of RAM.

Or, review that RAM in the hex editor tool, and see the exact address of the strange sprite. Set a breakpoint for writes to that RAM area, and try to figure out where those numbers are coming from.

Learning to debug is an important lesson. I spend at least 25% of my time fixing bugs.
Ok, sorry for the inconvenience. And I detected the fault. Upon update the sprite, the FOR performed it four times instead of one. Why did that bug.

Thank you for your explanations. There are things that I find hard to understand, but I try to move on. I look much your example to find solutions, and as you see, for now it seems that everything works fine.

What do you like my alpha 0.08? This afternoon add weapon selection on the menu.

And a technical question is it better to have a single function with many instructions or have multiple functions with separate instructions? For example, in the function movi_logic() I store the movement of all: player, enemies menu arrow, weapons, etc ... would it be better to give a movement function separately to each thing? Does it affect the performance?

UPDATE: I have already managed to make a functional menu, and then select to catch and weapon.
https://dl.dropboxusercontent.com/u/319 ... 00.09c.nes

Spanish:
Ok, perdona por la molestia. Ya detecté el fallo. Al hacer el update del sprite, el FOR lo realizaba cuatro veces en vez de una. Por eso daba ese error.

Gracias por tus explicaciones. Hay cosas que me resultan difíciles de entender, pero me esfuerzo por seguir adelante. Miro mucho tus ejemplo para buscar soluciones, y como ves, por ahora parece que todo funciona bien.

¿Que te a parecido mi alpha 0.08? Esta tarde añadiré la selección de armas en el menú.

Y una pregunta técnica ¿es mejor tener una sola función con muchas instrucciones o tener varias funciones con instrucciones separadas? Por ejemplo, en la función movi_logic almaceno el movimiento de TODO: player, enemigos, flecha del menu, armas, etc... ¿seria mejor dar una funcion de movimiento separada a cada cosa? ¿afecta al rendimiento?

UPDATE: Ya he conseguido hacer un menú funcional, y poder coger y luego seleccionar arma.

Re: NES Programming Blog

Posted: Sun Mar 06, 2016 8:58 am
by tokumaru
Diskover wrote:And a technical question is it better to have a single function with many instructions or have multiple functions with separate instructions? For example, in the function movi_logic() I store the movement of all: player, enemies menu arrow, weapons, etc ... would it be better to give a movement function separately to each thing? Does it affect the performance?
It's generally easier and more organized to isolate tasks as much as possible. There is an impact on performance, since each function call needs at least 12 cycles more than inlined code, because of the JSR and the RTS, plus whatever time is needed to handle parameters, return values and such, but depending on the overall complexity of the game, that might not even make a difference.

I suggest you try to make things as organized as you can, so the code is easy to maintain. Use whatever structure you're most comfortable working with. Then later on, IF
you detect any performance issues, you do something about it.

Re: NES Programming Blog

Posted: Sun Mar 06, 2016 2:31 pm
by na_th_an
cc65 needs inline functions. That would make code both readable and fast in those cases you are using functions that will be called just once in your code (just for organization). I've coded some stuff for the SEGA 8-bit consoles in SDCC and inline functions, which that compiler supports, are a great feature.

In my case, I use a dirty trick (dirty, dirty) if I want to keep things organized but I don't want to spend cycles calling functions (for example, when packing up small tasks from NMI to sprite 0 collision detection for splits): I just put the code to another file and use a #include in the main. This is ugly C code, but it does the job for me.

Code: Select all

	switch (ent) {
		case 1:
			#include "enems_linear.h"
			break;
		case 2:
			#include "enems_gyrosaw.h"
			break;
		case 3:
			#include "enems_buzzer.h"
			break;
		case 4:
			#include "enems_pezon.h"
			break;
		case 5:
			#include "enems_fanty.h"
			break;
		case 6: 
			#include "enems_bloco.h"
			break;
		case 7:
			#include "enems_final_frog.h"
			break;
	}

Re: NES Programming Blog

Posted: Sun Mar 06, 2016 2:42 pm
by rainwarrior
You can use a preprocessor macro (#define) as a substitute for inline functions. It's also handy for unrolling loops.

Re: NES Programming Blog

Posted: Sun Mar 06, 2016 2:54 pm
by DRW
Edit: rainwarror was faster.

Yeah, inline functions would be good here.

Because for every called sub routine, the assembly code uses a JSR and an RTS. But writing everything in one function could become hard to read.

However, as a workaround, you can use macros:

Code: Select all

#define MovePlayer()\
do\
{\
    Task1();\
    Task2();\
}\
while (0)
The do while (0) is done, so that you don't run into problems in this situation:

Code: Select all

if (a == 3)
    MovePlayer();
else
    SomethingElse();
If you didn't have the do while (0), the compiler would complain because of the semicolon since the macro would be translated to this:

Code: Select all

if (a == 3)
{
    Task1();
    Task2();
}; /* <-- Error if followed by an else. */
else
    SomethingElse();
So, you would be forced to write:

Code: Select all

if (a == 3)
    MovePlayer()
else
    SomethingElse();
which doesn't look good.
That's why do while (0) is the best. (It doesn't add anything to the compiled code. Both versions would create exactly the same output.)

Re: NES Programming Blog

Posted: Sun Mar 06, 2016 3:14 pm
by na_th_an
I use defines it for simple functions I want to inline and of course to unroll loops, but the syntax has its caveats and it's a bit ugly, so when the function is complex, it can be a PITA to maintain if it's writen as a define. That's why I use the #include hack for longer, more complex functions I'd rather inline.

Re: NES Programming Blog

Posted: Sun Mar 06, 2016 4:30 pm
by DRW
I would say if the function is really complex, then an additional JSR, RTS won't really make a difference.

That's why I have a whole bunch of MoveCharacter functions (one for each different type of character) which are only used in one location in the whole program.
So, yes, the algorithms could be written directly since the functions are not resuable.
And yes, using a macro for these long functions would look really ugly.
So, I just use a regular function and call it a day. That's four additional JSR, RTS per frame. If the game will ever lag, I don't think that will be the main issue.

Re: NES Programming Blog

Posted: Sun Mar 06, 2016 4:33 pm
by Diskover
na_th_an wrote:cc65 needs inline functions. That would make code both readable and fast in those cases you are using functions that will be called just once in your code (just for organization). I've coded some stuff for the SEGA 8-bit consoles in SDCC and inline functions, which that compiler supports, are a great feature.

In my case, I use a dirty trick (dirty, dirty) if I want to keep things organized but I don't want to spend cycles calling functions (for example, when packing up small tasks from NMI to sprite 0 collision detection for splits): I just put the code to another file and use a #include in the main. This is ugly C code, but it does the job for me.
I will study. Sometimes I use as I should switch.

Spanish:
Lo estudiaré. Algunas veces uso switch según me conviene.
rainwarrior wrote:You can use a preprocessor macro (#define) as a substitute for inline functions. It's also handy for unrolling loops.
DRW wrote:Edit: rainwarror was faster.

Yeah, inline functions would be good here.

Because for every called sub routine, the assembly code uses a JSR and an RTS. But writing everything in one function could become hard to read.
If, in fact I already use quite the macro (#define), especially on the issue of ordering some things and that code does not become something endless. It is more comfortable to work.

Spanish:
Si, de hecho ya utilizo bastante las macro (#define), sobre todo por el tema de ordenar un poco las cosas y que el código no se convierta en algo interminable. Es más cómodo de trabajar.

Re: NES Programming Blog

Posted: Wed Mar 09, 2016 3:04 pm
by Diskover
Well, I think you have to teach a little of my progress in this area. Little by little I'm improving something:

- Added select menu items.
- Added collision box walls.
- Added lives, energy and points.
- Added screen Continue and Game Over.
- Added top scorer. It contains points system, selected weapon, lives and energy player.
- I added two more maps.
- I added music and sound (testing).

Some of these things I had to guide me a little with the demo Spacy3 dougeff, especially with the score and music. The music is taken directly from that demo. I have been researching the operation of Famitone, and the truth is that it is very complicated. I'll leave it to the last of all.

ROM: https://dl.dropboxusercontent.com/u/319 ... 00.12b.nes

Image Image Image

Spanish:
Bueno, creo que os tengo que enseñar un poco de mis avances en la materia. Poco a poco voy mejorando alguna cosa:

- Añadido menú de selección de objetos.
- Añadido colisión de caja con paredes.
- Añadidas vidas, energía y puntos.
- Añadido pantalla de Continue y Game Over.
- Añadido marcador superior. Contiene sistema de puntos, arma seleccionada, vidas y energía del player.
- He añadido dos mapas más.
- He añadido música y sonido (en pruebas).

Parte de estas cosas me he tenido que guiar un poco con la demo Spacy3 de dougeff, sobre todo con el marcador y la música. La música esta cogida directamente de esa demo. He estado investigando el funcionamiento de Famitone, y la verdad es que es muy complicado. Lo dejaré para lo último de todo.

Re: NES Programming Blog

Posted: Wed Mar 09, 2016 3:27 pm
by dougeff
Looks good.

Maybe now would be a good time to start your own forum thread... perhaps over in the 'homebrew' section.

Re: NES Programming Blog

Posted: Wed Mar 09, 2016 10:36 pm
by dougeff
Pushing the box is a little buggy.

Also, wait till you're in v-blank before turning on an off the screen. You're getting 1 frame of misaligned screens, every time you press 'start' or change rooms.

Example (por ejemplo) you step into a door, which triggers the code to load the next room...

1.wait for v-blank...as...

from my example code, wait for NMI_flag != 0

2. Now, turn the screen 'off' ...All_Off();
3. Load the next room's data to PPU
4. Blank the sprites from the last room (move them off screen)...Blank_sprite();
5. Set the position of hero for new room, and position of other sprites, etc.
6. wait for v-blank...Wait_Vblank();

_Wait_Vblank:
lda $2002
bpl _Wait_Vblank

7. reset NMI_flag = 0;
8. turn the screen'on' and nmi's 'on' ...All_On();
9. back to regular game loop

Re: NES Programming Blog

Posted: Thu Mar 10, 2016 8:33 am
by Diskover
dougeff wrote:Pushing the box is a little buggy.

Also, wait till you're in v-blank before turning on an off the screen. You're getting 1 frame of misaligned screens, every time you press 'start' or change rooms.

Example (por ejemplo) you step into a door, which triggers the code to load the next room...

1.wait for v-blank...as...

from my example code, wait for NMI_flag != 0

2. Now, turn the screen 'off' ...All_Off();
3. Load the next room's data to PPU
4. Blank the sprites from the last room (move them off screen)...Blank_sprite();
5. Set the position of hero for new room, and position of other sprites, etc.
6. wait for v-blank...Wait_Vblank();

_Wait_Vblank:
lda $2002
bpl _Wait_Vblank

7. reset NMI_flag = 0;
8. turn the screen'on' and nmi's 'on' ...All_On();
9. back to regular game loop
Basically I do all that you say, but nevertheless do not get to solve that problem.

It seems silly but that frame gets to be problems with the collision map by charging and that the player has not yet been put in place.

As much as I try and change, I can not fix the problem.

Spanish:
Básicamente hago todo eso que dices, pero sin embargo no consigo solucionar ese problema.

Parece una tontería pero ese frame consigue que haya problemas con el mapa de colisiones al cargarle y que el player no se haya colocado todavía en su sitio.

Por más que pruebo y cambio, no consigo solucionar el problema.

Re: NES Programming Blog

Posted: Thu Mar 10, 2016 1:22 pm
by dougeff
I don't have your source code, but setting a breakpoint for writes to $2001 and $2005-6 shows me this...while pressing 'Start'. (and viewing the sprite buffer in the hex editor).

-screen is turned off at scanline 79, giving 1 frame that is 1/4 drawn.
-while the sprite buffer is set to have all Y positions at $f8 (off screen), the buffer is not pushed to the OAM, so when the screen is turned back on...(at scanline 241, the start of v-blank)...the OAM is still filled with the last screen's sprites. Sprites are visible for 1 frame.

(Start pressed again)...

-screen is turned off at scanline 24, which shows no visible errors, but is technically not the right time to turn off the screen (outside of v-blank)
-screen is turned on at scanline 241 (the start of v-blank)...but for a whole frame, the scroll position is not set, and the PPU address $28c0 is still in the PPU address, which misaligns the screen for 1 frame.

OK, also...you are setting $2000-2001 twice every frame...both during v-blank, so no visible errors, but still not necessary. And, the screen is flip-flopping back and forth between nametable #0 and nametable #1. It's not visible, because both sceens are loaded with identical data, but certainly not necessary (as far as I can tell).

So...solutions.
Add...
OAM_ADDRESS = 0;
OAM_DMA = 2;

after you blank the sprites.

Add...
SCROLL = 0;
SCROLL = 0;

at the end of the All_On function

figure out why $2000/2001 is being written to twice, why nametables are switching, and how to wait for v-blank before turning the screen off (preferably using the NMI_flag).

Re: NES Programming Blog

Posted: Sun Mar 13, 2016 1:47 pm
by dougeff
I've added a few pages on 6502 ASM coding to my blog.

http://nesdoug.com/2016/03/10/26-asm-basics/

If anyone out there (who knows this stuff) is willing to look it over, and make sure I didn't make any errors, I would appreciate it. :)

Although, no rush, really. My statistic thing says I only get about 40 viewers a day, and almost none have them looked at the ASM pages. I just don't like to post errant information. Speaking of...

This document, which I had on my computer, and referenced when looking up ASM instructions...
http://nesdev.com/6502.txt
Incorrectly lists PLA as setting no flags.

Re: NES Programming Blog

Posted: Mon May 09, 2016 5:58 pm
by dougeff
Hey, I made my first YouTube instructable video today. It's not very good (I did about 5 minutes of prep). It's just a quick how-to on using NES screen tool.

https://youtu.be/BtV_NCwWAqs

I have plans to make a few more on FCEUX debugging tools, and such.

(Interesting side note, I modified the palette of my NES Screen Tool and replaced it with Kizuls palette

viewtopic.php?f=21&t=13555

The palette was easy to find {hex editor} since Shiru posted the source code).