"object oriented" programming, scripting?

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

Post Reply
User avatar
GradualGames
Posts: 1107
Joined: Sun Nov 09, 2008 9:18 pm
Location: Pennsylvania, USA
Contact:

"object oriented" programming, scripting?

Post by GradualGames » Thu Nov 20, 2008 7:37 am

Has anyone gone so far as to try to emulate object oriented concepts when writing their NES games? Has anyone created any sort of scripting language, even maybe some sort of byte code that represents commands, but you have some kind of macro in your .asm file for what that bytecode is? I wonder if that would even make sense, since presumably once a ROM is burnt you can't really add new functionality to the game. What is your thinking on these issues?

Regards,
-Zom
total NES n00b

User avatar
SecretServiceDude
Posts: 99
Joined: Wed Oct 22, 2008 3:49 pm
Location: Los Angeles, CA

Post by SecretServiceDude » Thu Nov 20, 2008 12:44 pm

If I were coding in C++, I'd have classes like Player with member functions such as Player::Init(), Player::Update(), Player::Jump(), Player::Shoot(), and so on.

I try to emulate this paradigm somewhat in my 6502 programming. I name each of my routines such that they begin with the name of the "class" it operates on. For example, all my player routines have names like PLAYER_Init, PLAYER_Update, PLAYER_Jump, and PLAYER_Shoot. Likewise with routines such as INPUT_Init/INPUT_Update, SOUND_Init/SOUND_Update, and so on.

Additionally, each "class" gets its own .asm and .inc files. So I have files such as player.asm/.inc, input.asm/.inc, sound.asm/.inc, etc. The .inc files specify only the routines that must be publicly accessible. All other routines are confined to their respective .asm files but their symbols aren't exported. So as far as the rest of the program is concerned, those routines don't exist. This arrangement somewhat emulates the "private" concept of C++ and helps keep things neatly organized.

Almost every object in my game contains at least two routines: XXX_Init, which is called once at initialization, and XXX_Update, which is called once per frame. These routines will often call other routines that are specific to that particular object. For instance, my PLAYER_Update routine will make calls to routines such as Player_UpdateMovement and Player_UpdateFiring. In many cases, the XXX_Init and XXX_Update routines are the only routines that are ever made publicly accessible via my .inc files. Everything else is hidden away.

The main difference between my 6502 and C++ coding styles is that member functions in C++ take an additional argument (the 'this' pointer), which I don't emulate in my 6502 coding. Instead, I make extensive use of globals due to their low overhead. In fact, I so far have never pushed any arguments onto the stack. Instead, I allocate several "temp" variables in zero page and use those for any arguments I can't pass via registers.

User avatar
Bregalad
Posts: 7889
Joined: Fri Nov 12, 2004 2:49 pm
Location: Chexbres, VD, Switzerland

Post by Bregalad » Thu Nov 20, 2008 2:30 pm

I try to emulate this paradigm somewhat in my 6502 programming. I name each of my routines such that they begin with the name of the "class" it operates on. For example, all my player routines have names like PLAYER_Init, PLAYER_Update, PLAYER_Jump, and PLAYER_Shoot. Likewise with routines such as INPUT_Init/INPUT_Update, SOUND_Init/SOUND_Update, and so on.
This is a great idea. I'm always searching for names I can remember for my labels, and often I fail greately so I should find the routine back to know its exact name.

I keep my files more or less separed as you said. It makes things easier in the end, dealing with a huge file is just very impratical.
The main difference between my 6502 and C++ coding styles is that member functions in C++ take an additional argument (the 'this' pointer), which I don't emulate in my 6502 coding. Instead, I make extensive use of globals due to their low overhead. In fact, I so far have never pushed any arguments onto the stack. Instead, I allocate several "temp" variables in zero page and use those for any arguments I can't pass via registers.
This is definitely the way of doing it. I don't know about the stack thing, but that's certainly not something to do with the 6502.
If there is 3 or less int agruments I pass them with A, X, Y. If there is more I pass them with Temp1-4, and if there is a pointer I pass it trough PointerL/PointerH variables. Also sometimes "globals" serves as arguments too. I like to use the carry as an output boolean.

Also if there is a few arguments that are always constant on each routine call (but different on different routine calls), a good idea is to put them as .db $xx after the jsr instruction, and modify the return adress as supposed in the routine. This saves bytes if used a couple of times.
Life is complex: it has both real and imaginary components.

User avatar
Memblers
Site Admin
Posts: 3858
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Post by Memblers » Thu Nov 20, 2008 8:14 pm

I always thought data for my animation code is kind of like a simple script. It specifies which frame to display and a fixed point delay before the next one, but what makes it interesting is the jump command which can be used for loop points or even jumping anywhere into a separate animation. I could add other commands, but haven't needed any yet.

Post Reply