Some of these ideas I don't really need at this time, but looking at what I may need from the perspective of a very large NES project, I have tried to implement things I may need in the future.
High Level code constructs
This is slowly evolving as I find things that don't quite work perfectly or something small gets added. See the documentation here: https://www.assembla.com/spaces/ca65hl/wiki
There is no code created by these macros. They work by creating labels, which CA65 can do utilizing the .sprint() and .ident() built-in functions. I may explain how they work at the macro level in more detail later, but as far as the IF-ENDIF structure, once a stack macro is implemented, tracking logical blocks and spitting out labels is not too difficult. The more difficult part was implementing the flexibility of what can be included as a 'boolean expression'.
Organizing code with libraries and header files
This is a simple but very nice way to organize chunks of code that can be reused later. This simple example is NES controller reading. You could code the routine once, and never have to worry about it again. (This example ignores the DPMC conflict.)
First, write the 'library' code. I've standardized on prefixing all filenames with 'lib_', so this is: lib_controller.inc
The .inc indicates that this is to be included somewhere in the project, it could be in a separate module. (Note, in this code func is a custom macro.)
Code:
.ifndef _LIB_CONTROLLER_ _LIB_CONTROLLER_ = 1 .scope _LIB_CONTROLLER_ ; keep everything in its own scope .pushseg .segment "ZEROPAGE" pressed: .res 2 ; new this frame - held down pressedLastFrame: .res 2 ; last frame / call pressedNew: .res 2 ; newly pressed since last frame releasedNew: .res 2 ; newly released since last frame .popseg exportfunc readPort exportfunc readPort0 exportfunc readPort1 .export pressed .export pressedLastFrame .export pressedNew .export releasedNew func readPort0 ldx #0 .byte $CD ; compare absolute, skip ldx #1 endfunc func readPort1 ldx #1 endfunc func readPort ; IN : player number in reg X = 0, or 1 => 1 or 2 ; OUT: Y: undefined, A: PadsNewReleased, X: unchanged lda pressed,x ; save last frame's joystick sta pressedLastFrame,x lda #1 sta pressed,x ; set bit0 to activate carry in do-while loop sta $4016 lsr a ; a has 0 sta $4016 : lda $4016,x and #3 ; famicom cmp #1 ; friendly reads rol pressed,x bcc :- lda pressed,x eor pressedLastFrame,x tay and pressed,x sta pressedNew,x tya eor pressedNew,x sta releasedNew,x rts endfunc .endscope .endifIf this has been included somewhere, now you can access this functionality from any module by including the header file: int_iController.h
; Interface for lib_controller.inc .ifndef _INT_CONTROLLER_H_ _INT_CONTROLLER_H_ = 1 .scope iController importfunc readPort0 importfunc readPort1 importfunc readPort .importZP pressed .importZP pressedLastFrame .importZP pressedNew .importZP releasedNew .endscope .endifAny module that includes the header file can access the controller reading functionality and the variables via the iController scope:
Somewhere in code:
; include the header: .include "int_iController.h"
; elsewhere: lda iController::pressednew and #BUTTON_A bne buttonApressed
This has the advantage of quickly reusing code and speeding up assembly of large projects, since the library code will never have to be assembled again if it is not changed.
Some minor improvements
Pass "-I headerFilefolder -I libraryFileFolder" to the command line of CA65 and keep all headers and libraries in a standard location.
I have standardized on a header file format of prefixing with int_ and created a macro to help make things a bit nicer.
Somewhere in code:
uses iControllerThis will attempt to include "int_iController.h" More to come next time.
Hey, will you ever finish this tutorial? I'm trying to start coding on the NES and ca65 with you macros seems the best way to go :)
ReplyDeleteI didn't stick with the blog thing as much as I would have liked. I am working on some things still, but still some ways away from really releasing anything. See: http://ca65hlx.comeze.com
ReplyDeleteSend me (Movax12) a message on forums.nesdev.com to contact me effectively.