A translation unit means a source code file, the source code files it includes, and all source code files thereby recursively included. For example, if "bg.s" includes "nes.inc" and "global.inc", and "global.inc" further includes "enemytypes.inc", the translation unit consists of those four files. In the C programming language and in the ca65 assembler, each translation unit is compiled or assembled to one relocatable object code (.o) file, and once all translation units are compiled, the .o files are linked together into an executable.
In ca65, as in C, a function or variable can be marked as private to a translation unit. In C, a function or global variable is made private if marked static; in ca65, it is made private by not naming the function or variable in an .export statement. Two different translation units can have private functions or variables with the same name, reducing the likelihood of an accidental name collision.
ASM6, by contrast, allows only one translation unit in a program. Every function or variable can see every other function or variable, so long as it isn't defined within the body of a scoping structure (macro or rept).
A representative snippet from an audio driver:
If I were to modify it to avoid name collisions by namespacing all private symbols, it would appear as follows:
Likewise, music pattern data would change from this, where each measure occupies one line of code:
to this:
Is the latter in each pair still readable? Is this sort of insistent namespacing considered a good practice in ASM6 libraries?
I admit that in the specific case of music pattern data, the data is most commonly created with pentlyas.py, which compiles the score in an MML-like language to a bytecode score. But I can envision a situation in which the composer chooses not to run pentlyas.py (because of past "coiler" frustration with Python interpreter version incompatibility). In this case, the composer will be manually editing this bytecode in the file.
In ca65, as in C, a function or variable can be marked as private to a translation unit. In C, a function or global variable is made private if marked static; in ca65, it is made private by not naming the function or variable in an .export statement. Two different translation units can have private functions or variables with the same name, reducing the likelihood of an accidental name collision.
ASM6, by contrast, allows only one translation unit in a program. Every function or variable can see every other function or variable, so long as it isn't defined within the body of a scoping structure (macro or rept).
A representative snippet from an audio driver:
Code:
lda (conductorPos),y
sta musicPattern,x
iny
lda (conductorPos),y
sta patternTranspose,x
iny
lda (conductorPos),y
sta noteInstrument,x
jsr startPattern
sta musicPattern,x
iny
lda (conductorPos),y
sta patternTranspose,x
iny
lda (conductorPos),y
sta noteInstrument,x
jsr startPattern
If I were to modify it to avoid name collisions by namespacing all private symbols, it would appear as follows:
Code:
lda (_pently_internal_conductorPos),y
sta _pently_internal_musicPattern,x
iny
lda (_pently_internal_conductorPos),y
sta _pently_internal_patternTranspose,x
iny
lda (_pently_internal_conductorPos),y
sta _pently_internal_noteInstrument,x
jsr _pently_internal_startPattern
sta _pently_internal_musicPattern,x
iny
lda (_pently_internal_conductorPos),y
sta _pently_internal_patternTranspose,x
iny
lda (_pently_internal_conductorPos),y
sta _pently_internal_noteInstrument,x
jsr _pently_internal_startPattern
Likewise, music pattern data would change from this, where each measure occupies one line of code:
Code:
PPDAT_bf98_melodyA:
.byte REST|D_D8,N_D|D_8,REST,N_F|D_8,REST
.byte N_DS|D_8,N_F,N_DS|D_8,REST,N_C|D_8,REST
.byte N_D|D_8,N_DS,N_F|D_8,REST,N_AS|D_8,REST
.byte GRACE,5,N_GS,N_AS|D_D8,N_GS|D_4,N_TIE,REST
.byte PATEND
.byte REST|D_D8,N_D|D_8,REST,N_F|D_8,REST
.byte N_DS|D_8,N_F,N_DS|D_8,REST,N_C|D_8,REST
.byte N_D|D_8,N_DS,N_F|D_8,REST,N_AS|D_8,REST
.byte GRACE,5,N_GS,N_AS|D_D8,N_GS|D_4,N_TIE,REST
.byte PATEND
to this:
Code:
PPDAT_bf98_melodyA:
.byte PENTLY_PAT_REST|PENTLY_PAT_D_D8,PENTLY_PAT_N_D|PENTLY_PAT_D_8,PENTLY_PAT_REST,PENTLY_PAT_N_F|PENTLY_PAT_D_8,PENTLY_PAT_REST
.byte PENTLY_PAT_N_DS|PENTLY_PAT_D_8,PENTLY_PAT_N_F,PENTLY_PAT_N_DS|PENTLY_PAT_D_8,PENTLY_PAT_REST,PENTLY_PAT_N_C|PENTLY_PAT_D_8,PENTLY_PAT_REST
.byte PENTLY_PAT_N_D|PENTLY_PAT_D_8,PENTLY_PAT_N_DS,PENTLY_PAT_N_F|PENTLY_PAT_D_8,PENTLY_PAT_REST,PENTLY_PAT_N_AS|PENTLY_PAT_D_8,PENTLY_PAT_REST
.byte PENTLY_PAT_GRACE,5,PENTLY_PAT_N_GS,PENTLY_PAT_N_AS|PENTLY_PAT_D_D8,PENTLY_PAT_N_GS|PENTLY_PAT_D_4,PENTLY_PAT_N_TIE,PENTLY_PAT_REST
.byte PENTLY_PAT_PATEND
.byte PENTLY_PAT_REST|PENTLY_PAT_D_D8,PENTLY_PAT_N_D|PENTLY_PAT_D_8,PENTLY_PAT_REST,PENTLY_PAT_N_F|PENTLY_PAT_D_8,PENTLY_PAT_REST
.byte PENTLY_PAT_N_DS|PENTLY_PAT_D_8,PENTLY_PAT_N_F,PENTLY_PAT_N_DS|PENTLY_PAT_D_8,PENTLY_PAT_REST,PENTLY_PAT_N_C|PENTLY_PAT_D_8,PENTLY_PAT_REST
.byte PENTLY_PAT_N_D|PENTLY_PAT_D_8,PENTLY_PAT_N_DS,PENTLY_PAT_N_F|PENTLY_PAT_D_8,PENTLY_PAT_REST,PENTLY_PAT_N_AS|PENTLY_PAT_D_8,PENTLY_PAT_REST
.byte PENTLY_PAT_GRACE,5,PENTLY_PAT_N_GS,PENTLY_PAT_N_AS|PENTLY_PAT_D_D8,PENTLY_PAT_N_GS|PENTLY_PAT_D_4,PENTLY_PAT_N_TIE,PENTLY_PAT_REST
.byte PENTLY_PAT_PATEND
Is the latter in each pair still readable? Is this sort of insistent namespacing considered a good practice in ASM6 libraries?
I admit that in the specific case of music pattern data, the data is most commonly created with pentlyas.py, which compiles the score in an MML-like language to a bytecode score. But I can envision a situation in which the composer chooses not to run pentlyas.py (because of past "coiler" frustration with Python interpreter version incompatibility). In this case, the composer will be manually editing this bytecode in the file.