spca65
Moderator: Moderators
Forum rules
- For making cartridges of your Super NES games, see Reproduction.
Re: spca65
OK, now a doc on making an SPC-700 ca65 linker config file (read previous ca65 linker doc first):
spc700-config.md
And an update to spc-chord, now builds an SPC music file as well, and without an added embedded .zip file (thanks Ubuntu!):
spc-chord-2.zip
spc700-config.md
And an update to spc-chord, now builds an SPC music file as well, and without an added embedded .zip file (thanks Ubuntu!):
spc-chord-2.zip
Re: spca65
About the BSS tricks section, you may be able to get the same effect with the SYMBOLS section in the linker configuration. The SYMBOLS section allows importing symbols from code modules as well as exporting new symbols. This allows you to control the placement of code without touching the linker configuration, such as:
Code: Select all
; test.cfg
SYMBOLS {
romAddr: type = import;
}
MEMORY {
ROM: start = romAddr, size = $A000 - romAddr;
}
SEGMENTS {
CODE: load = ROM, type = ro;
}
; test.s
.export romAddr = $6000
; See where we're at.
.word *
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
Re: spca65
Oh nice, much cleaner than my hack.
I've been working towards a sp65c02 test and I'm surprised at how compatible this will be. The four main status flags are even in the same bit positions on the saved status on the stack: NV-- --ZC.
I think RTS is the only notable problem that will have to be accepted. It doesn't increment the return address by one, so code using it for indirect jumping will fail. RTI however works the same, so that (IMO superior) approach to indirect jump can be shared without change.
I've made PLA, PLX, and PLY set the status flags properly, by adding an INC+DEC after. Minor cost for compatibility. I might add an option to disable these.
I've been working towards a sp65c02 test and I'm surprised at how compatible this will be. The four main status flags are even in the same bit positions on the saved status on the stack: NV-- --ZC.
I think RTS is the only notable problem that will have to be accepted. It doesn't increment the return address by one, so code using it for indirect jumping will fail. RTI however works the same, so that (IMO superior) approach to indirect jump can be shared without change.
I've made PLA, PLX, and PLY set the status flags properly, by adding an INC+DEC after. Minor cost for compatibility. I might add an option to disable these.
Re: spca65
It's probably being really pedantic, but and a,#$ff should shave off two cycles for the PLA case while not consuming more space.
EDIT: and I would say to leave this behavior on. Instead, offer a new pl[axy] nf instruction on both the 6502 and SPC700 targets to imply that flags are not necessary. Obviously on the 6502 the flags would be calculated anyway, but on the SPC700 the flag calculation step could be skipped, resulting in more optimal code.
EDIT: and I would say to leave this behavior on. Instead, offer a new pl[axy] nf instruction on both the 6502 and SPC700 targets to imply that flags are not necessary. Obviously on the 6502 the flags would be calculated anyway, but on the SPC700 the flag calculation step could be skipped, resulting in more optimal code.
Last edited by Near on Sat Nov 30, 2013 11:48 am, edited 1 time in total.
Re: spca65
That or a new macro rtsaddr that acts like .addr but subtracts one on platforms where needed.blargg wrote:I think RTS is the only notable problem that will have to be accepted. It doesn't increment the return address by one, so code using it for indirect jumping will fail. RTI however works the same, so that (IMO superior) approach to indirect jump can be shared without change.
Re: spca65
Or as noted, enable leading dots in identifiers and make .rtsaddr. But then you'd need handling of a split table, so you'd want a constant, rts_offset, and then a directive to make a table/split table with all addresses at some offset.
If you're going to modify the code to work with sp65c02, then you might as well just have it use RTI and work without any special constants or macros.
And ahhh, that's how you do AND A,A, as you do on the 80xx/Z80-series to set flags except carry.
If you're going to modify the code to work with sp65c02, then you might as well just have it use RTI and work without any special constants or macros.
I was aiming for consistency between PLA, PLX, and PLY. But I've already implicitly decided that instruction timing is not something to depend on, and PLA is literally infinitely more common in Rockwell 6502 code.byuu wrote:It's probably being really pedantic, but and a,#$ff should shave off two cycles for the PLA case while not consuming more space.
And ahhh, that's how you do AND A,A, as you do on the 80xx/Z80-series to set flags except carry.
If it is, one can just use SPC pop instructions and write a macro for 65xx. POP A, POP X, POP Y. I don't think optimality is critical, as the SPC-700 has so many more optimal instructions, like MOV dp,#imm. That would be the better direction for optimality, allow writing a subset of SPC-700 code on the 65C02. So clearly developer convenience/familiarity takes front seat.EDIT: and I would say to leave this behavior on. Instead, offer a new pl[axy] nf instruction on both the 6502 and SPC700 targets to imply that flags are not necessary. Obviously on the 6502 the flags would be calculated anyway, but on the SPC700 the flag calculation step could be skipped, resulting in more optimal code.
Re: spca65
Small update of sp65c02 macros:
spc65-0.1.1.zip
Just fixes PLA, PLX, and PLY to set Z and N, and adds BRK #n as on 65C02.
I've confirmed that as far as A, X, Y, S, memory, and bits 8, 7, 1, and 0 of the status flags go, all these instructions behave identically on the 65C02 emulation mode of the 65816 and the sp65c02 macros:
Also, all the data addressing modes behave the same.
I've rewritten my testing framework to be all 6502 code at the core (with platform-specific customization at the edges), and now it assembles and works on the NES, SNES, and SPC-700. Things like CRC calculation, hex printing, and framework logic all use the same code. Great idea, tepples!
spc65-0.1.1.zip
Just fixes PLA, PLX, and PLY to set Z and N, and adds BRK #n as on 65C02.
I've confirmed that as far as A, X, Y, S, memory, and bits 8, 7, 1, and 0 of the status flags go, all these instructions behave identically on the 65C02 emulation mode of the 65816 and the sp65c02 macros:
Code: Select all
CMP abs
ADC abs
SBC abs
AND abs
EOR abs
ORA abs
DEC abs
INC abs
ASL abs
LSR abs
ROL abs
ROR abs
INC
PHA
PHP
PLA
PLP
TAX
TXA
TXS
TSX
RTI
I've rewritten my testing framework to be all 6502 code at the core (with platform-specific customization at the edges), and now it assembles and works on the NES, SNES, and SPC-700. Things like CRC calculation, hex printing, and framework logic all use the same code. Great idea, tepples!
Re: spca65
Indeed, and very nice execution. This project inspired me to write my own "assembler" with ca65 directives, but for the SuperFX. I might post something if it turns out well.blargg wrote:Great idea, tepples!
Re: spca65
I got the itch for GB-Z80 three hours ago and now I've got the initial instruction test passing for everything just now. Easier the second time I guess.
Re: spca65
Here's my ongoing sketch of 6502 on GB-Z80, not sure whether I can take it seriously enough to try:tepples wrote:[6502-in-drag] might not work so well for far-less-6502-like coprocessors such as GBZ80 and Super FX. That's where macro packages come in.
Code: Select all
a a
x c (b=0)
y e (d=0)
tsx ld hl, sp+0
ld c, l
tax ld c, a
or a
txa ld a, c
or a
lda #imm ld a, imm
or a
lda abs ld a, (abs)
or a
ldx #imm ld c, imm-1
inc c
sta abs ld (abs), a
stx abs ld hl, abs
ld (hl), c
cmp #imm cp imm
cpx #imm ldh (temp), a
ld a, c
cp imm
ldh a, (temp)
jsr abs call abs
pha push psw
pla pop psw
or a
plp ldh (temp), a
pop psw
ldh a, (temp)
jmp abs jp abs
bne rel jr nz, rel
adc #imm adc imm
adc abs ld hl, abs
adc (hl)
dec abs ld hl, abs
dec (hl)
asl abs ld hl, abs
sla (hl)
lda $nnnn,x ld hl, $nnnn
add hl, bc
ld a, (hl)
If anyone else (tepples?) would actually benefit, I could find motivation to try it. It would be useful for sharing my test framework code, which has pretty lax performance/size requirements.
Re: spca65
Is it as comically poor as the match between either 6502 family and C or 8080 family and C? Perhaps if someone has an idea for something that's intermediate between 6502 and Z80, he could open a topic in GBDev and explain.
In any case, I wasn't thinking of actually running unmodified 6502 code on a Z80. I just wanted to get 6502 code going on SPC700 for my music engine (thank you for your work so far), as well as explore 6502-like syntaxes for other architectures such as Z80 and 68000 as a bridge to help an NES programmer learn them. For example, the data registers of 68000 could be called A-H and the address registers Z-S (where S is conveniently A7, the stack pointer).
In any case, I wasn't thinking of actually running unmodified 6502 code on a Z80. I just wanted to get 6502 code going on SPC700 for my music engine (thank you for your work so far), as well as explore 6502-like syntaxes for other architectures such as Z80 and 68000 as a bridge to help an NES programmer learn them. For example, the data registers of 68000 could be called A-H and the address registers Z-S (where S is conveniently A7, the stack pointer).
Re: spca65
ca65 has some real head-scratchers sometimes:
So add :: to every use of a global symbol in your macros. I'll need to fix the spc-700 macros, as they run into this issue.
Also, instant swap-space filler (have a killall ca65 ready in another terminal):
Code: Select all
foo = 0
.if foo ; works
.endif
.scope
.if foo ; Error: Constant expression expected
.endif
.if ::foo ; works
.endif
.endscope
Also, instant swap-space filler (have a killall ca65 ready in another terminal):
Code: Select all
.macro foo
.scope
foo: ; oops, same name as macro
.endmacro
foo
Re: spca65
Yeah, this is a really unfortunate feature. When ca65 sees the "foo" in the scope, it plays it safe and assumes that another "foo" could be declared later in the same scope, and thus the symbol is non-constant, even if there's no actual "foo" inside the scope. It's unfortunate given how rare the use case of redefining an existing symbol inside the current scope is.blargg wrote:ca65 has some real head-scratchers sometimes:So add :: to every use of a global symbol in your macros. I'll need to fix the spc-700 macros, as they run into this issue.Code: Select all
foo = 0 .if foo ; works .endif .scope .if foo ; Error: Constant expression expected .endif .if ::foo ; works .endif .endscope
Equally annoying is that if there are nested anonymous scopes, sometimes there's simply no way to reference symbols in some of the scopes.
This is the reason why I prefer .local instead of .scope to make symbols defined inside the macro local to the macro. But even .local is stupid, because the use case of needing to define global symbols inside the macro is much more rare, so the default should be that all symbols are local to the macro. But it is what it is...
This issue/feature has been discussed a couple of times over at the cc65 mailing list.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
Re: spca65
Take a look at this Stack Overflow question.blargg wrote:ca65 has some real head-scratchers sometimes
Not in one of my projects. There's a macro that sets up a big data table and generates a local symbol for each entry because the table's entries form several circularly linked lists of entries that are variants of the same item.thefox wrote:the use case of needing to define global symbols inside the macro is much more rare
...Now take a look at when that SO question got answered.
Re: spca65
And next, how to define a global symbol within a scope? (and split this topic-drift into an "Advanced ca65 techniques" thread?) All I've found is this total hack:
The context is using scopes in a nice loop macro, so having to name each scope ruins most of the convenience.
EDIT: Yay, more breakage with scopes. .referenced/.ifref doesn't see usages of symbols in a scope:
Code: Select all
.scope
nop
: ; anonymous label isn't scoped
nop
.endscope
global = :- ; reference anonymous label
EDIT: Yay, more breakage with scopes. .referenced/.ifref doesn't see usages of symbols in a scope:
Code: Select all
jsr foo
.scope
jsr bar
.endscope
.ifref foo
.out "1" ; printed
.endif
.ifref bar
.out "2" ; not printed
.endif
foo:
bar: