Hot answers tagged

18

The Fix for cc65 This was discussed in cc65 issue #946 and fixed by cc65 PR #965. That was merged to the master branch on 2019-10-26, and should appear in V2.19 of cc65. (I don't know when that release will happen, however; it's been five months since the last release.) It is, however, quite easy to do your own build of cc65 if you want to use the master ...


13

Since the inline assembler of cc65 doesn't accept anonymous labels (from my other answer), another approach is to provide a unique suffix to the labels, which can be applied by the macro. The stringizing operator of the C preprocessor, and the fact that C string literals written consecutively are automatically concatenated, might make this more convenient: #...


12

Simple reason CL65 is using "C64" target as default, while CA65 uses "none". Adding a -t none should make this disappear. Details: The CL65 documentation for -t does clearly point out the difference: -t sys, --target sys The default for this option is different from the compiler and linker in the case that the option is missing: While ...


10

TL;DR: This macro will solve your issues: .feature string_escapes .macro PString Arg .byte :++ - :+ : .byte Arg : .endmacro When called with more than one argument the arguments have to be quoted in curly brackets. Due enabled string-escapes C like strings can be handled as well. 000800 1 03 41 42 43 PString "ABC&...


8

Your source is most likely in ISO 8859-1 (or -15) encoded (*1), so the compiler has to do code conversion between character literals in your source and the designated target. Without a specifying a target CL65 uses, unlike all other tools, the C64 target by default (*2). As specified in target.c line 193, the C64 Target uses the PETSCII table at line 113, ...


7

Is there an escape character in ca65 to add such commands to a text string? In general: No. The whole ASCII(Z) mechanic is meant to write device independent code, so adding device specific sequences is rather outside of the scope. To get arbitary inserts, you may want to use the good old .BYTE: msg .BYTE "Hello ",$05,"World",0 Then ...


5

There is a pseudo variable __AX__ of type unsigned int that can be assigned a value that then ends up in register A (lo byte) and X (hi byte). So, the following macro definition works as intended: #define set_bgcolor(C) (__AX__ = (C),asm("sta $D021")) I found this under "Extensions" in the cc65 user guide.


4

(Caveat: This is from memory with a quick peek into the manual. So some reply after trying it might be useful.) TL;DR; Fill it Try fill=yes (*1) for the memory area of MAIN and make HIMEMSEG overwrite the area you added: MEMORY { ZP: file = "", start = $0002, size = $00FE, define = yes; LOADADDR: file = %O, start = %S - 2, size =...


4

You can use anonymous labels in ca65. The equivalent to your example code using these, but without the C wrapping, would be: CMP #$60 BCC :+ AND #$DF BNE :++ : AND #$3F : You can also use :- to refer to an anonymous label preceding the current position. Increasing the number of + or - symbols increases the number of anonymous labels to skip over. ...


4

Preface: I'm not the world greatest C expert - not at least as I dislike C quite a lot :)) What Happenes The general issue here is that CC65 puts the address into a pointer variable, visible when looking at the generated source: .segment "DATA" _myfunction2: .word $FFD2 Later that variable gets loaded onto the stack - like CC65 does with ...


3

How do I set up multiple banks on an NES ROM using ca65/ld65? Do you have a clear description how that ROM structured? Or, nowadays it's more like, how the 'ROM' file structure for that system (and configuration) is? CA65 does not know, nor do I (And I'm not going to dissect emulators now). Since the banks can be slotted in at will at runtime, how can I ...


3

It appears the answer is no: ca65 is a single-pass assembler and unlike C and NASM, there is not a stand-alone preprocessing stage in the assembly process. Moreover, the design of some of the assembler’s features would make it pretty difficult to support: The implementation of local symbols has the assembler internally re-write the identifiers into forms ...


3

Adding this to the code as per @tofro's suggestion: unsigned char kernel_getin(void *ptr, unsigned char *size) { unsigned char * data = (unsigned char *)ptr; unsigned char i; unsigned char st=0; for(i=0; i<*size; i++) { st = cbm_k_readst(); if (st) break; data[i] = cbm_k_getin(); } data[i] = '\0'; ...


2

I would expect that the CC65 compiler, like most compilers, would output string literals using whatever sequence of bytes appears in the source file. If you want to ensure that particular byte values get included in a string, you can use a backslash followed by a three-digit octal number to include any byte value within a string. While one could use fewer ...


2

Like the name says, they are numeric variables. They can hold numbers and nothing else. This is confirmed by the documentation. I would instead try something like this: __word_last .set 0 __word_0 = 0 .macro defword strname .ident (.sprintf("__word_%u", __word_last + 1)): .addr .ident(.sprintf("__word_%u", __word_last)) ....


1

ca65 doesn't seem particularly retro to me but you could do it recursively: .macro StringHelper p0, p1, p2, p3, p4 .ifnblank p0 .byte p0 StringHelper p1, p2, p3, p4 .endif .endmacro .macro MultiPString p0, p1, p2, p3, p4 .local begin,end .byte end-begin begin: StringHelper p0, p1, p2, p3, p4 end: .endmacro or ...


1

ca65 was designed as a single-pass assembler. So this works: addr = 4096 .byte $9e,.sprintf("%d", addr) but this does not: .byte $9e,.sprintf("%d", addr) addr = 4096 --> Error: Constant expression expected The expression can't simply be constant; it must be constant and has to be defined before the sprintf ...


Only top voted, non community-wiki answers of a minimum length are eligible