spca65

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: spca65

Post by blargg »

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
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: spca65

Post by thefox »

blargg wrote:Doc on ca65 linker files:

ca65-linker-doc.md
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 *
See http://www.cc65.org/snapshot-doc/ld65-5.html#ss5.10 for more information.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: spca65

Post by blargg »

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.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: spca65

Post by Near »

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.
Last edited by Near on Sat Nov 30, 2013 11:48 am, edited 1 time in total.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: spca65

Post by tepples »

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.
That or a new macro rtsaddr that acts like .addr but subtracts one on platforms where needed.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: spca65

Post by blargg »

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.
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.
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.

And ahhh, that's how you do AND A,A, as you do on the 80xx/Z80-series to set flags except carry.
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.
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.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: spca65

Post by blargg »

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:

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
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!
ARM9
Posts: 57
Joined: Sun Aug 11, 2013 6:07 am

Re: spca65

Post by ARM9 »

blargg wrote:Great idea, tepples!
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.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: spca65

Post by blargg »

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.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: spca65

Post by blargg »

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.
Here's my ongoing sketch of 6502 on GB-Z80, not sure whether I can take it seriously enough to try:

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)
It's such a comically poor match.

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.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: spca65

Post by tepples »

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).
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: spca65

Post by blargg »

ca65 has some real head-scratchers sometimes:

Code: Select all

foo = 0

.if foo ; works
.endif

.scope
	.if foo ; Error: Constant expression expected
	.endif
	
	.if ::foo ; works
	.endif
.endscope
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

.macro foo
.scope
foo: ; oops, same name as macro
.endmacro
foo
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: spca65

Post by thefox »

blargg wrote:ca65 has some real head-scratchers sometimes:

Code: Select all

foo = 0

.if foo ; works
.endif

.scope
	.if foo ; Error: Constant expression expected
	.endif
	
	.if ::foo ; works
	.endif
.endscope
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.
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.

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
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: spca65

Post by tepples »

blargg wrote:ca65 has some real head-scratchers sometimes
Take a look at this Stack Overflow question.
thefox wrote:the use case of needing to define global symbols inside the macro is much more rare
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.


...Now take a look at when that SO question got answered.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: spca65

Post by blargg »

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:

Code: Select all

.scope
    nop
:  ; anonymous label isn't scoped
    nop
.endscope
global = :- ; reference anonymous label
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

    jsr foo
.scope
    jsr bar
.endscope

.ifref foo
    .out "1" ; printed
.endif

.ifref bar
    .out "2" ; not printed
.endif

foo:
bar:
Post Reply