Do you use source control?
Moderator: Moderators
- GradualGames
- Posts: 1106
- Joined: Sun Nov 09, 2008 9:18 pm
- Location: Pennsylvania, USA
- Contact:
Do you use source control?
Do you use source control for your NES projects? I've been using it since about July or August, and I personally find it has many more benefits beyond just coordinating with other developers. I like the ability to efficiently try, fail, revert, try, fail, revert if I am attempting something new that I am somewhat unsure about. Previously I had to rename files dozens of times and had a big mess on my hands; source control abstracts this part of the development process.
I don't. I'm comfortable with the file/folder structure I use.
All my programs have "source" and "assets" folders, which I further organize as necessary. The "source" folder has folders for categories like "video" and "audio" where code and data specific to those areas are. There is also a different folder for each "module" of the game, such as title screen, level gameplay, and so on. The actual code is divided in several asm files. Each subroutine has it's own file, that carries it's name preceded by "sub_". Each table also has it's own file, with it's name preceded by "table_". Small tables and subroutines that are only used by a single subroutine can stay in that subroutine's file with temporary labels.
All of this is coordinated by a master asm file at the root of "source", that includes all the files at the locations they should be in the ROM. This may seem complicated, but has helped me a lot. Locating subroutines is a lot easier, as is having many of them visible at the same time. This also prevents the existence of extremely long files (but some subroutines are extremely long, there is no way around those).
In addition to all of that, at the end of the day I make backups of whatever projects I worked on during that day.
Just in case, here's a message for tepples: Please don't compare me to BumpityBoo.
All my programs have "source" and "assets" folders, which I further organize as necessary. The "source" folder has folders for categories like "video" and "audio" where code and data specific to those areas are. There is also a different folder for each "module" of the game, such as title screen, level gameplay, and so on. The actual code is divided in several asm files. Each subroutine has it's own file, that carries it's name preceded by "sub_". Each table also has it's own file, with it's name preceded by "table_". Small tables and subroutines that are only used by a single subroutine can stay in that subroutine's file with temporary labels.
All of this is coordinated by a master asm file at the root of "source", that includes all the files at the locations they should be in the ROM. This may seem complicated, but has helped me a lot. Locating subroutines is a lot easier, as is having many of them visible at the same time. This also prevents the existence of extremely long files (but some subroutines are extremely long, there is no way around those).
In addition to all of that, at the end of the day I make backups of whatever projects I worked on during that day.
Just in case, here's a message for tepples: Please don't compare me to BumpityBoo.
Bregalad: http://en.wikipedia.org/wiki/Revision_control
tokumaru: Your source code files are shorter than mine, but otherwise, I follow a similar structure. I also have a folder called "obj" where files generated from other files (e.g. .chr from .bmp/.png, .o from .s, etc.) go.
tokumaru: Your source code files are shorter than mine, but otherwise, I follow a similar structure. I also have a folder called "obj" where files generated from other files (e.g. .chr from .bmp/.png, .o from .s, etc.) go.
- Hojo_Norem
- Posts: 132
- Joined: Mon Apr 16, 2007 10:07 am
- Contact:
If I remember correctly, source control (eg CVS or SVN) works kind like a physical library does. You have a project with all its files and for some reason you want to work on a portion of it so you 'check it out' of the system. Once you do that nobody else is able to do so. You work on the portion you checked out and then submit the new version back and the code becomes available again. If you make a balls-up of it and somebody else notices they can revert it back to the previous version (like you can with a Wiki).Bregalad wrote:What is source control anyways ?
Anyhoow, thats how I remember it being taught nearly 10 years ago.
edit: tepples beat me to it
Insert witty sig. here...
I see. My CHRs go into the "assets" folder, along with binary tables. I chose not to deal with .o files, because they confuse the crap out of me (I really don't understand them), by using ASM6 (which just spits out my .nes file ready to go).tepples wrote:tokumaru: Your source code files are shorter than mine, but otherwise, I follow a similar structure. I also have a folder called "obj" where files generated from other files (e.g. .chr from .bmp/.png, .o from .s, etc.) go.
-
Celius
- Posts: 2159
- Joined: Sun Jun 05, 2005 2:04 pm
- Location: Minneapolis, Minnesota, United States
- Contact:
All of my projects are organized sort of like what was described by tokumaru, but a bit different. I of course have everything under a folder called whatever the name of the project is, and then everything is categorized from there. I have a "Code" folder, which contains all the pieces of code that make up the game engine, and a "Data" folder, which contains things like levels, graphics, you know, data. Above these folders, a "main" source file links everything together from these folders.
Within each folder, things are separated into another subfolder, but I don't usually go beyond that. In each subfolder is code or data (depending on whether it is under code or data) relating to its name. So for example, the CHR files will be under Data, and then under "Graphics". Or the code for drawing objects will be under Code, and then "ObjectDraw". In each of these subfolders, there is a file bundling everything in the subfolder all together, and that file is included in the "main" file. There is usually also a file that defines variables and macros for each subfolder, and I include this at the beginning of the "main" file.
Also, to help with this, I use kind of a class system for naming my routines and variables. For example, all of the AI routines will be named something like "AI.Process" or "AI.SpawnObject". And variables are named the same way. Unfortunately, I started a big project and there is nothing to distinguish between a label and a variable name, which is probably something I should have thought of before. But for now, I feel pretty organized and nothing is very difficult to change at all. Actually, since I have it set up the way I do, I am able to add and remove things with much ease. Maybe it's just a sloppy mess, but I think my system works for me.
Within each folder, things are separated into another subfolder, but I don't usually go beyond that. In each subfolder is code or data (depending on whether it is under code or data) relating to its name. So for example, the CHR files will be under Data, and then under "Graphics". Or the code for drawing objects will be under Code, and then "ObjectDraw". In each of these subfolders, there is a file bundling everything in the subfolder all together, and that file is included in the "main" file. There is usually also a file that defines variables and macros for each subfolder, and I include this at the beginning of the "main" file.
Also, to help with this, I use kind of a class system for naming my routines and variables. For example, all of the AI routines will be named something like "AI.Process" or "AI.SpawnObject". And variables are named the same way. Unfortunately, I started a big project and there is nothing to distinguish between a label and a variable name, which is probably something I should have thought of before. But for now, I feel pretty organized and nothing is very difficult to change at all. Actually, since I have it set up the way I do, I am able to add and remove things with much ease. Maybe it's just a sloppy mess, but I think my system works for me.
I try to name all my labels like we name methods in OO programs, they are all actions, describing what happens from the point where they are onwards. I use names like "ClearCoordinates", "UpdateScroll", and things like that, so that they sound like commands, not like variables. Sometimes what happens under a label isn't so clear and it's hard to pick a name, but I usually figure something out. Also, only the label of the main subroutine of a file (the one that names the file) is a global label, all others are temporary/local, because they are only used by the main subroutine.Celius wrote:Unfortunately, I started a big project and there is nothing to distinguish between a label and a variable name, which is probably something I should have thought of before.
I do sometimes feel the need to do something like this, to make it clear who owns the "methods", but I can't seem to think of something that will work for all cases.Also, to help with this, I use kind of a class system for naming my routines and variables.
Like you, I do find it easy to locate things in my sources and don't feel the need for any version control whatsoever. Specially considering that I constantly use 3 different computers (sometimes more) to work on my projects, so for me it works better to move my most recent daily backups around.
With ca65, you have the notion of modules and scope which help a lot for managing access to symbols.
I don't go as far as to separate all function in it's own file but usually I separate by their responsibilities. If I have something related to the view, it will go in the ViewManager.asm, for sound, SoundManager.asm etc. If one module contains a sub responsibility but share some of the variables, I will not create a new module but create a different file called ViewManager.metasprite.inc and include it. This avoid exporting variables just for that specific part and make the main file smaller.
For ZP variable usually I use zp in front of them but nothing for normal ones. I try to give command for label like Tokumaru but in the past I may have not followed that rule well so I will have to clean up the code someday. Inside a module, my function are always preceded with sub so if I see a function call with sub, I now it was a call from that module. Then when a module is exported, I create a scope inside the H file. So when I need to use the init method from the view, I don't need to call it subViewManagerInit , which would "pollute" the namespace inside the VienManager module but only do so when I export it. So inside ViewManager, you call subInit but outside it , I create a scope so I can call it this way: ViewManager::Init.
To do this, ca65 allow you to export name under a different one. For example, inside the view manager, you export the method this way:
Then inside my header file (ViewManager.h) I will define my scope this way:
Now I can call it like an object. Usually I will put some inner scope for variable too.
I use struct to define the location of item in memory to avoid using magic numbers for position. If the position of an item change, only the struct is affected, not the code.
Another thing I started recently is to rename my temp variable in the .proc scope to make the code easier to read. Usually what you use the temp variables is either for paramters or local temp variable but if your variable are called Param1, param2, param3, temp8bit etc, you lose the meaning of the usage of that temp variable compared to higher level language. Since I decided to give up for now my stack based parameter for my current project, I had to make a new naming convention. This is how I ended up doing it:
So if I want to use a parameter, I will do Param::entityPosX. It will be quite clear in the code what is the value inside. Same thing for the local variable Local::entityDir. If someday I have some code that could conflict by using the same temp variable, instead to have to code all the code, I only have to scan the definition at the top.
And when it times to set the parameter, I will do this:
The code document itself. I want to set the paramter entityPosX for the subPutEntityInOam function. It does make names longer but once the code is working, hwo many time will you change this? And how easier will it be to debug it in 6 month? That's the advantage, for maintenance.
I may have other things but this is what comes to mind when I code with ca65. My way of doing things changed a lot in 1 year. I always try new things when I have time to make my code simpler to maintain, the thing many people tends to forget not only for hobby but in the professional world too.
Edit:
About source control, the subject of this thread ( ^^;; ), I don't use it for now. I usually make a backup of the complete project for a specific day before doing some edit to it.
I don't go as far as to separate all function in it's own file but usually I separate by their responsibilities. If I have something related to the view, it will go in the ViewManager.asm, for sound, SoundManager.asm etc. If one module contains a sub responsibility but share some of the variables, I will not create a new module but create a different file called ViewManager.metasprite.inc and include it. This avoid exporting variables just for that specific part and make the main file smaller.
For ZP variable usually I use zp in front of them but nothing for normal ones. I try to give command for label like Tokumaru but in the past I may have not followed that rule well so I will have to clean up the code someday. Inside a module, my function are always preceded with sub so if I see a function call with sub, I now it was a call from that module. Then when a module is exported, I create a scope inside the H file. So when I need to use the init method from the view, I don't need to call it subViewManagerInit , which would "pollute" the namespace inside the VienManager module but only do so when I export it. So inside ViewManager, you call subInit but outside it , I create a scope so I can call it this way: ViewManager::Init.
To do this, ca65 allow you to export name under a different one. For example, inside the view manager, you export the method this way:
Code: Select all
.export __subViewManagerInit := subInit
Code: Select all
.import __subViewManagerInit
.scope ViewManager
Init = __subViewManagerInit
.endscope
I use struct to define the location of item in memory to avoid using magic numbers for position. If the position of an item change, only the struct is affected, not the code.
Another thing I started recently is to rename my temp variable in the .proc scope to make the code easier to read. Usually what you use the temp variables is either for paramters or local temp variable but if your variable are called Param1, param2, param3, temp8bit etc, you lose the meaning of the usage of that temp variable compared to higher level language. Since I decided to give up for now my stack based parameter for my current project, I had to make a new naming convention. This is how I ended up doing it:
Code: Select all
.proc subPutEntityInOam
;---------------- Parameters definitions ----------------
.scope Param
entityPosX = zpParam1 ; X coordinate
entityPosY = zpParam2 ; Y coordinate
entityDir = zpParam3 ; Which direction entity is facing
entityAdr = zpParam4 ; Adress of data, uses zpParam5 too
.endscope
.scope Local
centerSprite = zpTemp8Bit ; Use 1 temp8Bit for center or sprite retrival
entityMetaSpriteAdr = zpTemp16Bit
.endscope
;---------------------------------------------------------
And when it times to set the parameter, I will do this:
Code: Select all
lda #$00
sta subPutEntityInOam::Param::entityPosX
I may have other things but this is what comes to mind when I code with ca65. My way of doing things changed a lot in 1 year. I always try new things when I have time to make my code simpler to maintain, the thing many people tends to forget not only for hobby but in the professional world too.
Edit:
About source control, the subject of this thread ( ^^;; ), I don't use it for now. I usually make a backup of the complete project for a specific day before doing some edit to it.
- cpow
- NESICIDE developer
- Posts: 1097
- Joined: Mon Oct 13, 2008 7:55 pm
- Location: Minneapolis, MN
- Contact:
It was a good comparative laugh, though. Thanks!tokumaru wrote:I don't. I'm comfortable with the file/folder structure I use.
Please don't compare me to BumpityBoo.
I use CM [ClearCase, Subversion] all of the time at work and have been thinking about Subversion for home use. I have tens of NESICIDE.mmddyyyy named folders on a couple of different memory sticks, on my home PC, and on my work laptop [no, I never work on my NES projects at work...never...]. Sometimes it's fun to go look at the early days, but I don't have ANY rhyme or reason to why I cut a .ddmmyyyy folder on that particular .ddmmyyyy.
- GradualGames
- Posts: 1106
- Joined: Sun Nov 09, 2008 9:18 pm
- Location: Pennsylvania, USA
- Contact:
This is precisely the reason I use source control---it abstracts the process of timestamping and backing up your project at a particular state. In addition, it encourages you to make a comment about what that particular revision had changed in it. Not to mention it allows you to selectively look at differences between files, etc.NESICIDE wrote:It was a good comparative laugh, though. Thanks!tokumaru wrote:I don't. I'm comfortable with the file/folder structure I use.
Please don't compare me to BumpityBoo.
I use CM [ClearCase, Subversion] all of the time at work and have been thinking about Subversion for home use. I have tens of NESICIDE.mmddyyyy named folders on a couple of different memory sticks, on my home PC, and on my work laptop [no, I never work on my NES projects at work...never...]. Sometimes it's fun to go look at the early days, but I don't have ANY rhyme or reason to why I cut a .ddmmyyyy folder on that particular .ddmmyyyy.
In addition, I've learned that individual revision files are very small, so it allows you to back up your project in dozens of past states but with a lot less disk space than backing the entire thing up each day.
I can't imagine working without it now. I saw someone mentioned git---I've considered switching to git. I wish it had a nice GUI interface like Tortoise though =)
Wish granted.Gradualore wrote:I saw someone mentioned git---I've considered switching to git. I wish it had a nice GUI interface like Tortoise though =)