Jump to content
IGNORED

CA65 Assembler & linker


Recommended Posts

For those that don't know, these tools come with the CC65 compiler.

I have had several problems with the assembler and linker so I've started this thread to see if the problems I'm having are bugs, if there are work arounds, if I'm doing something wrong, or whatever.

I'll put each code sample in separate posts.

Link to comment
Share on other sites

What we have here is a work around.
I don't have a copy of the original code but I'll try to explain/recreate it enough it can be tested.

The original code did not define scrval or coltable, the code was inline and I used < and > for extracting the LSB and MSB.
Oddly enough, the same operators work in similar code elsewhere.
As far as I can tell, the parser is barfing on the long sequences of math operations I use to build the data differently for individual platforms.
The original code looked something like this with the data spread over 3 or 4 lines:

scrtableLSB:
    <ScreenAdr+(BytesPerLine**0, <ScreenAdr+(BytesPerLine**1,...

The error was that it was treating the resulting numbers as 16 bit rather than 8 bit, as if the < > operators were not there.

This worked, but I had to define .scrval separately to get it to work.

.if BytesPerLine = 40	
;**************************************************
; 80 column address lookup table
;**************************************************
.define scrval		ScreenAdr+BytesPerLine*8
.define coltable 	scrval*0, scrval*1, scrval*2, scrval*3, scrval*4, scrval*5, scrval*6, scrval*7, scrval*8, scrval*9, scrval*10, scrval*11, scrval*12, scrval*13, scrval*14, scrval*15, scrval*16, scrval*17, scrval*18, scrval*19, scrval*20, scrval*21, scrval*22, scrval*23, scrval*24	
scrtableLSB:
	.lobytes	coltable
scrtableMSB:
	.hibytes	coltable
.endif

Edited by JamesD
Link to comment
Share on other sites

This is a macro for simplifying the 65816 memory move, the assembler has been told to support 65816 code. Other macros I'm using work fine.

.macro	MOVEMEMN	StartAddress,DestAddress,BytesToMove,SourceBank,DestBank
	rep	#$30
.A16
.I16	
	LDX	#StartAddress
	LDY	#DestAddress
	LDD	#BytesToMove
	MVN	SourceBank DestBank
	sep	#$30
.A8
.I8
.endmacro

Here is how the program is using it. The commented out version was the first attempt.
Notice the number of math operations... just like other code I've had trouble with.

.if Use65816 = 1
;	MOVEMEMN	(ScreenAdr+BytesPerLine*FontHeight, ScreenAdr, BytesPerLine*ScreenHeight*FontHeight-BytesPerLine*FontHeight, 0, 0)
	MOVEMEMN	(ScreenAdr+40*8, ScreenAdr, 40*23*8, 0, 0)
	ldx		#0
;@sloop:
.else
; the non 65816 code goes here
...

Here is the list of errors:

Print80,CA65(511): Error: ')' expected
Print80,CA65(79): Note: Macro was defined here
Print80,CA65(511): Error: ':' expected
Print80,CA65(79): Note: Macro was defined here
Print80,CA65(511): Unexpected trailing garbage characters

Print80,CA65(79): Note: Macro was defined here

Print80,CA65(511): Error: ',' expected

Print80,CA65(79): Note: Macro was defined here

Print80,CA65(511): Note: Macro parameter came from here

Print80,CA65(511): Unexpected trailing garbage characters

Print80,CA65(79): Note: Macro was defined here

Print80,CA65(511): Note: Macro parameter came from here

Link to comment
Share on other sites

I am not super-sure that .define is intended for what you are doing with it. I thought it just defines the presence or absence of a particular value for use in .ifdef statements...you seem to be using it to hold named values:

.define scrval ScreenAdr+BytesPerLine*8

 

I always just use an equate for that kind of thing -

scrval=ScreenAdr+BytesPerLine*8

Link to comment
Share on other sites

Please provide self-contained examples. Ideally (a) source file(s) which can be fed into the assembler to show the problem.

 

For example, I have no idea what ScreenAdr, BytesPerLine, FontHeight, etc. are defined to.

 

In your first post, does it make a difference if you enclose the parameter to "<" in parentheses? So

<(ScreenAdr+(BytesPerLine**0)

instead of

<ScreenAdr+(BytesPerLine**0
Link to comment
Share on other sites

I am not super-sure that .define is intended for what you are doing with it. I thought it just defines the presence or absence of a particular value for use in .ifdef statements...you seem to be using it to hold named values:

.define scrval ScreenAdr+BytesPerLine*8

 

I always just use an equate for that kind of thing -

scrval=ScreenAdr+BytesPerLine*8

There is an example under

11.44 .HIBYTES

http://www.cc65.org/doc/ca65-11.html#ss11.44

 

And I should probably change as much as I can from defines to equates and some of my problems will go away.

Link to comment
Share on other sites

I am using ca65 from cc65 compiler myself on a project. As far as I can tell what sanny suggested is completely right: You need to put round brackets around the whole expression. So your provided code example

 

<ScreenAdr+(BytesPerLine**0, <ScreenAdr+(BytesPerLine**1, ...

will of course result in 16 Bit values. This is intentional and is described in the provided documentation (»ca65 Users Guide«) in chapter 4. »Expressions«. Especially sub-chapters 4.2 »Size of expression result« and 4.5 »Available operators« are of importance.

 

Your code example will evaluate to something like this:

 

8 Bit + (16 Bit *  * 0, 8 Bit + (16 Bit * 8 ) * 1, ...

which results in

 

16 Bit, 16 Bit, ...

So you must do what sanny already told:

 

<(ScreenAdr + BytesPerLine * 8 * 0), <(ScreenAdr + BytesPerLine * 8 * 1), ...
Edited by Island2Live
Link to comment
Share on other sites

 

Please provide self-contained examples. Ideally (a) source file(s) which can be fed into the assembler to show the problem.

 

For example, I have no idea what ScreenAdr, BytesPerLine, FontHeight, etc. are defined to.

 

In your first post, does it make a difference if you enclose the parameter to "<" in parentheses? So

<(ScreenAdr+(BytesPerLine**0)

instead of

<ScreenAdr+(BytesPerLine**0

Actually, I thought I tried that on the first line of values and it still barfed on it. I may experiment with it a bit and get back to you.

It's working now so I'll leave that real code alone.

 

*edit*

BTW, ScreenAdr is defined as the Screen Address, BytesPerLine is 32 or 40 depending on how it's assembled, and FontHeight is 8.

For whatever reason, most of those are .defines and not equ. So I'm hoping the problem goes away with that change.

Edited by JamesD
Link to comment
Share on other sites

Current macro

.P816

;Memory Move Negative.  Move from hi to lo address.
;Memory is moved at the rate of seven clock cycles per byte.
.macro	MOVEMEMN	SourceAddress,DestAddress,BytesToMove,SourceBank,DestBank
	rep	#$30					; set A, X, and Y to 16 bit
.A16							; Tell assembler Accumulator is 16 bit
.I16							; Tell assembler Index registers are 16 bit
	LDX	#SourceAddress			; The source address for the memory move
	LDY	#DestAddress				; The destination address for the memory move
	LDA	#BytesToMove+1			; The number of bytes we want to move + 1 because MVN needs it
	MVN	SourceBank,DestBank		; RAM banks, should be 00,00 on 64K system
	sep	#$30					; set A, X, and Y to 8 bits
.A8								; Tell assembler Accumulator is 8 bit
.I8								; Tell assembler Index registers are 8 bit
.endmacro

This does not work

	MOVEMEMN	($75C0,$74C0,5888,0,0)
Link to comment
Share on other sites

Not a ca65 user, but you don't normally put macro parms in parens. What happens if you remove them ?

Winner winner chicken dinner

 

I was basing the code on an earlier macro I made

 

 

.macro PRINT	str
	lda #<str
	sta string
	lda #>str
	sta string+1
	jsr print
.endmacro

And this works

 

Endless:
	PRINT(String)				; print the string we just built
	clc
	bcc	  Endless

But notice... only 1 parameter

Edited by JamesD
Link to comment
Share on other sites

This is a bit of a problem.

I share a lot of code between the 65816 and 6502 versions for the unrolled scroll loop.
I also have an alternate scroll for the 65816 using the MVN instruction.
I have to test if I am generating 816 code and if I want to use the unrolled loop or not.
If I'm not using the 65816 MVN, or I'm just using the 6502, I want to generate the unrolled loop.
If it's for the 816 I have some optional code before and after the loop for changing A to 16 bit and back.
But the assembler hates me.

if unrollmore isn't defined (the define is nested in a test) it wants me to use .ifndef CRAP.
if unrollmore is 1 it wants me to use .if CRAP < 1
.ifndef should work even if CRAP is defined as 1

This gives me an Error: Identifier Expected in the .ifndef CRAP

.define Use65816	1
.define	unrollmore	0



.if Use65816 = 1
.if unrollmore = 0
	MOVEMEMN	(ScreenAdr+(BytesPerLine*FontHeight)),ScreenAdr,((BytesPerLine*ScreenHeight)-(BytesPerLine*FontHeight)),0,0
	; clear last line
	ldx		#(BytesPerLine*4)-1
	lda		BGColor
@sloop:
	sta		ScreenAdr+LastRow*FontHeight*BytesPerLine,x
	sta		ScreenAdr+LastRow*FontHeight*BytesPerLine+BytesPerLine*FontHeight/2,x
	dex
	bne		@sloop
.define CRAP  1
.endif
.endif

; assembler workaround for .if unrollmore = 1 OR Use65816 = 0
.ifndef CRAP

.if Use65816 = 1
;... set A to 16 bit etc...
.endif
;unrolled loop screen scroll goes here
.if Use65816 = 1
;... set A to 8 bit etc...
.endif

.endif
Edited by JamesD
Link to comment
Share on other sites

Hi!,

 

This is a bit of a problem.

 

I share a lot of code between the 65816 and 6502 versions for the unrolled scroll loop.

I also have an alternate scroll for the 65816 using the MVN instruction.

I have to test if I am generating 816 code and if I want to use the unrolled loop or not.

If I'm not using the 65816 MVN, or I'm just using the 6502, I want to generate the unrolled loop.

If it's for the 816 I have some optional code before and after the loop for changing A to 16 bit and back.

But the assembler hates me.

 

if unrollmore isn't defined (the define is nested in a test) it wants me to use .ifndef CRAP.

if unrollmore is 1 it wants me to use .if CRAP < 1

.ifndef should work even if CRAP is defined as 1

 

This gives me an Error: Identifier Expected in the .ifndef CRAP

I think you should read the CA65 manual (at http://cc65.github.io/doc/ca65.html) carefully.

 

Your example works using the correct syntax, see:

.define Use65816	1
.define	unrollmore	0



.if Use65816 = 1 .and unrollmore = 0
        .warning "inside block 1"
.endif

.if unrollmore = 1 .or Use65816 = 0
        .warning "inside block 2"
.endif
See, use ".and" and ".or". Also, the ".warning" are useful to follow which code path is being assembled.
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...