Organizing it All

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
Lucradan
Posts: 101
Joined: Wed Sep 21, 2016 12:08 pm

Organizing it All

Post by Lucradan »

What techniques can you recommend for organizing all the game assets and code during development?

Currently I'm using ASM6 and trying to parse the code into small files which I can easily reuse for other projects. But refactoring is extremely difficult and time consuming in this case.
User avatar
dougeff
Posts: 3078
Joined: Fri May 08, 2015 7:17 pm

Re: Organizing it All

Post by dougeff »

If you comment your code well, you can search for key words fairly easy, even in a monstrously oversized file.

"update", "buffer", "metasprite", "multiply", etc.

Then cut and paste from old file to new.

I happen to be fortunate, as I put a large chunk of example code on github, organized by subject. I can find 99% of what I'm looking up in seconds.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Organizing it All

Post by tokumaru »

I divide my games into modules: System, Video, Audio, Input, Intro, Level, Bonus, and so on. Each module has a declaration file, containing all constants, global variables and macros that belong to it. These files are included at the very top of the main assembly file.

Then, each subroutine, interrupt handler and data table is in a separate file. Subroutines and data tables used only by one subroutine may stay in that subroutine's file instead of getting their own (they're basically local to that specific subroutine). Local variables are declared in each subroutine's file. Parameters are local variables with global aliases.

Subroutine and table names are always prefixed by the name of the module they belong to (e.g. Level_MoveCamera). Parameter names (aliases) are prefixed by their subroutine's name (e.g. Level_MoveCamera_OffsetX). If a subroutine has different entry points, they're prefixed by the base subroutine name (e.g. Video_DecompressTiles_ToVRAM and Video_DecompressTiles_ToRAM).

All subroutines, interrupt handlers and data tables are included in the main file in the desired order to form the final ROM. I have separate folders for code (subroutines and interrupt handlers), tables and binary files. Binary files are not included directly in the main file, they have to be included in a data table file where they can be properly labeled.
User avatar
samophlange
Posts: 50
Joined: Sun Apr 08, 2018 11:45 pm
Location: Southern California

Re: Organizing it All

Post by samophlange »

tokumaru wrote:Local variables are declared in each subroutine's file. Parameters are local variables with global aliases.
Can you show an example? I'm not happy with the solution I've been using for locals and parameters, but I don't 100% know what you mean by this.
User avatar
gauauu
Posts: 779
Joined: Sat Jan 09, 2016 9:21 pm
Location: Central Illinois, USA
Contact:

Re: Organizing it All

Post by gauauu »

Another thing I that's not mentioned here, unless I missed it, is keep all assets in as developer-friendly format as possible. (I keep graphics in png format, maps in an easily-editable text format, metasprite definitions in a custom easy-to-edit format) Then do the necessary conversions at build time. That way you're not endlessly doing exports and copying/pasting data from tool exports.

It makes the build scripts more complicated, but in a big project, you'll thank yourself for it later when editing your assets for the millionth time.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Organizing it All

Post by tokumaru »

samophlange wrote:
tokumaru wrote:Local variables are declared in each subroutine's file. Parameters are local variables with global aliases.
Can you show an example? I'm not happy with the solution I've been using for locals and parameters, but I don't 100% know what you mean by this.
Here's what one of my routines could look in ASM6:

Code: Select all

DoSomething = $ ;using this instead of a regular label allows me to include the same subroutine in multiple banks

.enum System_Scratchpad ;use a region in ZP reserved for local variables
  DoSomething_FirstParameter = $ ;global alias for the first parameter
  -FirstParameter .dsb 1 ;use temporary labels for the local variables
  DoSomething_SecondParameter = $ ;global alias for the second parameter
  -SecondParameter .dsb 2
  -LocalVariable0 .dsb 2
  -LocalVariable1 .dsb 1
  DoSomething_ReturnValue0 = $ ;global alias for the first return value
  -ReturnValue0 .dsb 2
  DoSomething_ReturnValue1 = $ ;global alias for the second return value
  -ReturnValue1 .dsb 1
  DoSomething_LocalEnd = $ ;marks the end of the memory used by the subroutine
.ende

  ;do something
  clc
  lda -FirstParameter
  adc -SecondParameter+0
  sta -ReturnValue0+0
  lda -SecondParameter+1
  adc #$00
  sta -ReturnValue0+1

  rts ;return
Note: I don't use local labels in ASM6 (the ones starting with "@") because they are *too* local - even "nameless" labels (the ones starting with "-" or "+") will break the scope of the local labels. That basically means you can't mix and match both types of labels, and since I consider the nameless ones more versatile, I made the decision to use only those.

Anyway, the "DoSomething_LocalEnd" label is there in case you want to run this subroutine concurrently with others. Since they'll have to share the scratchpad RAM, instead of starting the locals from "System_Scratchpad" in a concurrent subroutine, you can start from "DoSomething_LocalEnd" (e.g. .enum DoSomething_LocalEnd) and you'll be sure they won't overwrite each other's variables.
gauauu wrote:keep all assets in as developer-friendly format as possible. (I keep graphics in png format, maps in an easily-editable text format, metasprite definitions in a custom easy-to-edit format) Then do the necessary conversions at build time. That way you're not endlessly doing exports and copying/pasting data from tool exports.
Yeah, definitely automate as much as you can so you don't have to constantly tweak things by hand after every little change.
calima
Posts: 1745
Joined: Tue Oct 06, 2015 10:16 am

Re: Organizing it All

Post by calima »

I write C ;)

Any general asm functions are one per file, usually an optimized C function for speed or size. Easy to lift to other projects.
User avatar
nesrocks
Posts: 563
Joined: Thu Aug 13, 2015 4:40 pm
Location: Rio de Janeiro - Brazil
Contact:

Re: Organizing it All

Post by nesrocks »

I find that working with pngs is totally backwards for productivity. Haven't figured the best way to work with palettes yet though.
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!
https://www.patreon.com/bitinkstudios <- Support me on Patreon!
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: Organizing it All

Post by lidnariq »

The right image editor will let you work with pngs and keep their palettes in order.

For example, mtpaint isn't amazing, but it's very lightweight and doesn't think it knows better than you when it comes to paletted images.

Personally, I just work in greyscale.
User avatar
nesrocks
Posts: 563
Joined: Thu Aug 13, 2015 4:40 pm
Location: Rio de Janeiro - Brazil
Contact:

Re: Organizing it All

Post by nesrocks »

I meant importing palettes to the assembly project. I find myself switching between including the bin ".pal" files directly and also using .byte hex declarations.
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!
https://www.patreon.com/bitinkstudios <- Support me on Patreon!
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Organizing it All

Post by tokumaru »

I usually write my own programs to convert images into tiles, so I can do slmost anything I need without relying on existing tools. Extracting palettes from image files is simple enough that you could generate .pal files from them automatically.

I personally prefer to work with 24-bit color images though, since not many programs handle indexed color images properly these days. I try to encode the palettes and other information (sprite size, etc.) in the image itself, do I don't need a bunch of command line arguments to perform the conversions.
Oziphantom
Posts: 1565
Joined: Tue Feb 07, 2017 2:03 am

Re: Organizing it All

Post by Oziphantom »

Asm is a Write Once, Use Once kind of language. The manual memory allocation, shared variables, custom banking requirements usually make it somewhat hard to share large amounts of code. Even the C++ games I've worked on most of the time while we have a common Engine we end up with a pile of new code that is only for the game.

For making and reusing ASM its best to make your "routines" into macros that allow you to specify temp variables, bank etc this way you can do a lot of includes somewhere and forget about it. If you use a decent assembler you can also use .proc to handle such things.

Games to long enough to write that when you want a routine you know from the last game you just go and get it and copy and paste, then modify it suit what the current game needs, as this will probably be done once every 2 years or so..

For such images it best to use something designed for the task, Deluxe Paint or its clones such as GrafX2, Pro Motion (NG) these give you direct pallete control, decent export options and in some cases will hold you to the machines limits in terms of colour placement etc.
Post Reply