This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

IF macro for ca65

IF macro for ca65
by on (#98965)
I like NESHLA but it's too limiting, and so I moved on to ca65 for various reasons. The things I liked about NESHLA I figured I could do without or get close enough to the same functionality with macros. I decided to recreate the if functionality with macros and I think it is working well. If anyone is interested I'll post the code up somewhere. What I am able to do is stuff like:

Code:

if {carry set}
   ; do code
endif

;or

if {equal}
 ; blah blah
endif

if {less}
 ; blah blah
endif



It should work with any number of nested ifs and should be easy enough to add your own keywords.
Re: IF macro for ca65
by on (#98968)
Look at a 6502 manual, There are opcodes for specific operations like this!

They are Branching Instrucions!

EDIT:

IF Carry Set = BCS
IF Equal = BEQ
IF Less = BMI(?)
Re: IF macro for ca65
by on (#98970)
I'm sure he knows that Hamtaro, since he made the macros and all (and the macros do translate to branch instructions when assembled). Assembly typically lacks indentation and logical blocks, so it's understandable that some people prefer to use macros to make things a little bit less low-level.
Re: IF macro for ca65
by on (#98971)
Hamtaro126 wrote:

IF Carry Set = BCS
IF Equal = BEQ
IF Less = BMI(?)


The macro would actually change carry set to BCC and equal to BNE since I want to enter the block of code if the flag is set.
In normal 6502 assembly Less is BCC, greater or equal is BCS (after a CMP instruction). That is how I implement it in the macro at least - NESHLA used the N flag >:(
Re: IF macro for ca65
by on (#98972)
Movax12 wrote:
NESHLA used the N flag >:(

Which is OK if you're dealing with signed numbers. The carry flag can be used for unsigned comparisons, while N and V should be used for signed numbers.
Re: IF macro for ca65
by on (#98973)
I think my brain would think about that better in terms of "is the result negative or not?" rather than less or greater, but I see your point.

So far I have:

Code:
; carry set
; carry clear
; no carry
; not carry
; C
; not C
; C set
; C clear
; less
; not less
; greater_equal
; not greater_equal
; zero
; zero clear
; zero set
; not zero
; equal
; not equal
; Z
; not Z
; Z set
; Z clear
; plus
; not plus
; positive
; not positive
; minus
; negative
; not minus
; not negative
; N
; not N
; N set
; N clear
; bit7
; bit7 set
; bit7 clear
; not bit7
; V
; overflow
; overflow set
; overflow clear
; not overflow
; V
; V set
; V clear
; not V
; bit6
; bit6 clear
; bit6 set
; not bit6


I'm not sure if I am implementing the macro as well as possible, but as long as I stick to the above formats I'm certain it will work. The code is here: http://sharetext.org/dDge
Re: IF macro for ca65
by on (#98974)
tokumaru wrote:
The carry flag can be used for unsigned comparisons, while N and V should be used for signed numbers.

Is there a standard test on 6502 for whether unsigned + signed (e.g. position + change) has overflowed unsigned?

Would it be hard to make macros for greater, not greater, less_equal, not less_equal, that use a branch on Z that jumps over a branch on C?

Would "else" be hard?
Re: IF macro for ca65
by on (#98975)
tepples wrote:
Would it be hard to make macros for greater, not greater, less_equal, not less_equal, that use a branch on Z that jumps over a branch on C?


Not hard at all. It also wouldn't be hard to implement do-while loops, or repeat-until.

Quote:
Would "else" be hard?


I briefly thought about that, it might not be too hard.. I'll think about it.
Re: IF macro for ca65
by on (#98999)
So I was implementing ELSE and I realized that trying to track IF/ENDIF pairs with numbers and math doesn't work. It may work most of the time, but it doesn't work all the time. The only proper way to do it is a stack, and actually it's much easier.

So ELSE is working and IF / ENDIF should be 100% reliable as far as matching up the code blocks properly.

http://shorttext.com/f3qe4k
Re: IF macro for ca65
by on (#99011)
I added greater and not greater. I also made some the flag checks more restrictive, like a flag name (Z for example) has to be followed by 'set' or 'clear'. I may add a do while loop and get back to actually coding some 6502. If anyone uses this and needs the code to be relocatable, change the jmp in the else macro to clv/bvc.

http://pastebin.com/PKjw89u8
EDIT: small changes: http://pastebin.com/Hvfr4EQh
Re: IF macro for ca65
by on (#99125)
I've polished this up quite a bit, there is some information here: http://mynesdev.blogspot.ca/2012/09/ca6 ... acros.html

The expression evaluation code has gone from a huge pile of .IFs down to this:

Code:
.macro process_expression_FLAGS flagtest, flag, flagisset

; Find a value for which flag we are checking and return:
   
   _n_ .set  (  (.xmatch(.left(1, {flagtest}) , no)) .or (.xmatch(.left(1, {flagtest}) , not))  ) ; not or no prefix
   
   flag .set (.xmatch(.mid(_n_,1, {flagtest}) , C)) * 1 + (.xmatch(.mid(_n_,1, {flagtest}) , Z)) * 2 + (.xmatch(.mid(_n_,1,{flagtest}) , N)) * 3 + (.xmatch(.mid(_n_,1,{flagtest}) , V)) * 4 + (.xmatch(.mid(_n_,1,{flagtest}) , G)) * 5
   
   flag_set_default .set (.xmatch(.mid(_n_+1,1, {flagtest}), set)) * 1 + (.xmatch(.mid(_n_+1,1, {flagtest}), clear)) *  -1

   .ifnblank .mid(_n_+2,1, {flagtest}) ; user added clear or set, also accept 'do' from "while <exp> do" syntax
      invert_flag          .set .xmatch(.mid(_n_+2,1, {flagtest}), clear) *  -1  + .xmatch(.mid(_n_+2,1, {flagtest}), set) * 1 + .xmatch(.mid(_n_+2,1, {flagtest}), do) * 1
   .else
      invert_flag          .set 1 ; no clear or set added, that's okay make it a 1
   .endif
   invert_flag             .set invert_flag * (_n_ * -2 + 1)
   
   .if ( (flag = 0) .or (flag_set_default = 0) .or (invert_flag =0))
      .error "Unknow expression in flag test."
      .fatal ""
   .endif
   
    flagisset .set ((flag_set_default * invert_flag) > 0) ; This will always result in a negative or positive, positive being flag is being tested for
   
.endmacro


It's working well I think, I'll publish all the code soon.

Updated! I am done for now - I'm going to try to actually use it in code. Any feedback welcomed. Code is available at the blog link I posted.
Re: IF macro for ca65
by on (#100347)
I'm trying out your macro package, and it seems it can't handle local labels within the conditions like in the following snippet:

Code:
    cmp #JOY_A
    if equal
        jmp @Freeze
    endif

    cmp #JOY_B
    if equal
        jmp @Melt
    endif
    lda #0
    rts


Removing the '@' from my label names works fine. While I realize that your macros are supposed to reduce the need for local labels, it would be nice if it didn't disable their usage in this way. Do you think it would be possible to make your macro package support this?...
Re: IF macro for ca65
by on (#100349)
Bananmos wrote:
Do you think it would be possible to make your macro package support this?...

As far as I know, it's not possible. The macros need to generate labels, and they'll always mess with the local (@) labels. I thought it might be possible to fix this by generating the label inside a scope, but looks like the @ labels don't care about scopes, so they'll get invalidated when any normal label comes. Then I thought it might be possible to generate the label using "foo = *" or "foo := *", but that also invalidates the local labels. As does "foo .set 123". That's all the possible workarounds I can think of...

P.S. Movax, why are you using .error followed by .fatal "", and not only .fatal?
Re: IF macro for ca65
by on (#100372)
.error outputs a line number with the string.
.fatal stops the assembly, but doesn't give a line number.

There are some minor issues with this too, but the worst error is if the branch is too far, ca65 won't tell you were the problem is in the main code, just in the macro. The branch generation could be changed to always use a jmp with a branch over and I've added an option to do that which isn't too complicated if anyone wants. It's too bad there is no way to decide if the branch is long or not in the macro code.

I don't see a way to use cheap local labels due to the generation of normal labels from the if macro(s)
Re: Converting a Lorom pcb cart to a hirom pcb cart
by on (#100396)
Is there a reason why you're not using macro-local labels?

I also have a bit of a problem with the Creative Commons license, which isn't really meant for code. One of the technicalities making it incompatible with some other licenses is the provision for requiring downstream users to remove credits. I'd have gone with this one.
Re: Converting a Lorom pcb cart to a hirom pcb cart
by on (#100399)
tepples wrote:
Is there a reason why you're not using macro-local labels?

I also have a bit of a problem with the Creative Commons license, which isn't really meant for code. One of the technicalities making it incompatible with some other licenses is the provision for requiring downstream users to remove credits. I'd have gone with this one.

Wrong thread? Anyway, it's not possible to use macro-local labels, because they are not visible from one macro to another. And even then, I have a feeling that they'll invalidate the local @ labels too, because under the hood CA65 is simply replacing their name with a unique identifier.
Re: IF macro for ca65
by on (#100401)
Oops, my bad. Fortunately, phpBB 3 lets moderators move posts from one topic to another.
Re: IF macro for ca65
by on (#100577)
After adding some .proc/.endproc directives, I guess the lack of local labels ain't that bad. The constructs do make my AI code and my in-game mapeditor code look a bit more readable, and this is exactly the place where I'd like to have some more readability and no having to think twice over what I'm writing, at the cost of less efficient code. (was considering doing all AI in Atalan, but it turned out to be too buggy so using these macros is a less drastic alternative)

Not sure about them in the rest of my game engine though, as I kind of want to keep my branches optimal there, and having to start thinking about what kind of branches the conditional constructs result in kind of defeats their purpose :)
Re: IF macro for ca65
by on (#100579)
There isn't a point to changing already completed and working code I don't think, though I did change a lot of mine, but mainly for testing purposes (I didn't ever run into a problem). The conditions will always assemble into one branch instruction except for greater / not greater so there should be no optimizing issues. (Greater should be substituted with greaterORequal where possible by comparing to a value+1)
Re: IF macro for ca65
by on (#100751)
I just had a hard-to-track down bug and realized that it again was due to label restrictions... it seems that introducing any sort of scoped labels in your file prevents you from using it. So this dummy example will fail to compile:

Code:
.SETCPU "6502X"
.include "hla.inc"

.CODE
if equal
    .byte $00
endif

.proc MyProc
if equal
    jsr $0000
endif
.endproc


But removing the if/endif which is outside the proc compiles fine. In this case, the two scopes are completely separate and don't interact in any way... so shouldn't it be possible to work around the label restriction here somehow, short of putting them into separate .asm files and compiling them separately? i.e, by somehow resetting the label counter before declaring MyProc, putting things in the same state as they are when you begin assembly?..
Re: IF macro for ca65
by on (#100758)
If you keep all your code inside a .scope or a .proc there should be no problem. I am a bit confused as to exactly the details of the issue (just looked at it for a couple minutes), but I think I could resolve the problem if this is something you need to be able to do, let me know if you really require this. - I'm probably going to play with it anyway...

EDIT: So I decided to change the code to work in that situation, I like it better - the problem was the way the macros were using the variable 'constants' for tracking numbers. I pasted the code at the blog link: http://mynesdev.blogspot.ca/2012/09/ca6 ... acros.html

But really it's probably better to keep your code inside a .proc

Oh, btw - I added an option to create a long jump in the IF macro which is in that code - I'm pretty sure it is working properly. :wink:
Re: IF macro for ca65
by on (#100836)
Quote:
So I decided to change the code to work in that situation, I like it better - the problem was the way the macros were using the variable 'constants' for tracking numbers


Thanks! Everything that failed prevously seems to work nicely now :)

Btw, can I come with one more improvement suggestion?... I saw on the previous page of this thread a discussion of comparing numbers as "greater/less" with respet to signed/unsigned numbers. The thing is that to handle this decently, you probably need to have distinct namings for this similar to what the x86 assembly instructions have:
http://unixwiz.net/techtips/x86-jumps.html

In summary, when using unsigned numbers the x86 assembly instructions use the "above"/"below" terminology, but when the numbers are signed it uses the "greater than"/"less than" terminology. It really doesn't take very long to get used to which is appropriate for unsigned/signed numbers, so I would recommend having some similar naming in your macro pack to be able to easily do both signed and unsigned comparison.
Re: IF macro for ca65
by on (#100849)
I don't want to add too much complexity to the macro code, even adding the greater and lessORequal I wasn't sure about.

You can use the syntax to call an additional macro like this example if you want more complexity:

Code:
.define padpressed(buttons) Z clear do_code padpressedMAC buttons


.macro padpressedMAC buttons
lda _pads_new_pressed
and #(buttons)
.endmacro


;...

if padpressed BUTTON_A|BUTTON_START
;...
endif



This will check for Z clear, so instead you could write some code and check for N flag based on the information here (section 5):

http://www.6502.org/tutorials/compare_beyond.html#5
Re: IF macro for ca65
by on (#100979)
I swore I wasn't going to do this, but I've done a lot of work to make the ability to call another macro quite a bit more useful. From a user (of this macro pack) perspective, all you need to do is make a .macro "function" like this example:

Code:

.macro padpressed buttons

   lda _pads_new_pressed
   and #(buttons)
   set_flag_test Z clear

.endmacro



So if you use any of the conditional macros, you can code like:

Code:

if padpressed BUTTON_A
; do stuff
endif



The difference here is that the macro function can specify what CPU flags to check and there is no inline function like before.

This allows for quite a bit of flexibility and I have both a signed and unsigned expression evaluation working that I'll post soon. Example:

Code:

if comp a > #3
;code
endif



Or signed:

Code:

if scomp a <= #(< -120)
;...
endif




The signed compare generates a bit of code and trashes reg a, but both can handle any comparison except for comparing registers to each other.

EDIT: () Brackets will be needed around any high/low byte operators
Re: IF macro for ca65
by on (#101053)
Updated! Try it out and let me know if there are any issues, it is somewhat untested, but I expect it almost bug free. There is a link to download a demo program and nes rom:

Small write-up: http://mynesdev.blogspot.ca/2012/10/ca6 ... dated.html
Download: https://app.dumptruck.goldenfrog.com/p/b9UI5-8_ck
Re: IF macro for ca65
by on (#101061)
How far can this be taken? Can you make asm look like a higher level language? I seem to remember a book in the early 90's about object oriented assembly. I assumed they used macros and stylistic rules to ape C++
Re: IF macro for ca65
by on (#101064)
MASM has stuff like .if/.else/.endif/.while/.break built in. A lot of modern assemblers have things like that, though sufficiently powerful macros can probably do all of that (at the expense of longer assembly times).
Re: IF macro for ca65
by on (#101065)
I thought .if directives in assembly language were evaluated at compile time, like C++ #if. At least that's how ca65 handles .if.
Re: IF macro for ca65
by on (#101066)
There's a lot less standardization when it comes to assemblers. MASM has directives that do both things: IF vs .IF.
Re: IF macro for ca65
by on (#101070)
I don't think there is much of a limit on how far you could go with enough macro code. As it is, none of these generate a lot of code - the signed comparison generates the most. If more complicated expressions were wanted they would have to result in more complex code being output. Interesting that MASM has support for this kind of thing.

EDIT: Actually there is a pretty bad error in the code highlevel.h due to a search and replace doing more than I expected, I'll update this post when it is fixed.. Fixed, links still valid.
Re: IF macro for ca65
by on (#101475)
Thanks for the tip about .macro "functions"... they really help making my code look nicer as testing various state flags in the AI code is just an if CUSTOM_CONDITION :)

The and/or support you talked about in another thread sure sounded interesting, even though this is already very useful as it stands.
Re: IF macro for ca65
by on (#101492)
I feel I kind of rushed things a bit before, so I'm trying to get things polished up a bit more this time but I'm almost ready to release some more stuff after I write up some decent documentation too.

I'm using dopple's smbdis.asm to test the macros, so maybe I can share that as well.
Re: IF macro for ca65
by on (#101572)
Still working on the documentation but I wanted to share this..

I'll document it better later, time to head to work..

http://mynesdev.blogspot.ca/2012/10/ca6 ... again.html

http://pastebin.com/azMMvh4r .. updated 1 times.

Documentation updated! I will add more but it explains most things well.
Re: IF macro for ca65
by on (#101887)
Another post on this topic, I tried to explain a bit about how it is working, sort of in between technical and more explanative, I hope this proves useful to others: http://mynesdev.blogspot.ca/2012/10/hl- ... nical.html
Re: IF macro for ca65
by on (#105290)
I've decided to keep this code updated here: https://www.assembla.com/code/ca65hl/git/nodes
I'm also going to use the wiki on that page to document it's use, though there is not much there yet.

This version also includes integrated <, >, <>, >= <= operators (unsigned) as well as the assignment macro and assignment macro supported operators &, |, ^ ( bitwise) +, - (clear/set carry) --, ++ (with carry), >>, <<, *, / (times and divide also shift left or right with powers of two.)

It will also default to behaving as if any non zero result is true if no cpu flags are specified and (hopefully) it makes sense to do so.
Re: IF macro for ca65
by on (#119352)
Announcing a new feature addition. Now featuring support for parentheses in expressions! Although I am confident I have everything working, please let me know if you find any mistakes. I would consider this untested, beta code.

https://www.assembla.com/code/ca65hl/git/nodes/devel

Following the same rules as the previous version, you can test 'expressions' that represent or result in a CPU flag being set/clear and branch appropriately. The latest code allows parentheses to create more complex logical conditions, as well as a negate operator that can distribute across parenthesis. The code generated aims to be efficient and will short circuit as soon as the outcome can be determined.

The only limitation is that all OR logic must be before all AND logic in the same parentheses set. ( Add parentheses to work around this.)

Example:

Code:

    ; branch to label:
    * = 8000
   
    foo = $00
    bar = $01
    baz = $03
    myLabel = * + $50
   
    if ( ( foo >= #$03 && ! bar ) || ((zero && negative) || baz = #1)) goto myLabel

    ; code output:   
    8000   A5 00      LDA $00
    8002   C9 03      CMP #$03
    8004   90 04      BCC $800A
    8006   A5 01      LDA $01
    8008   F0 46      BEQ $8050
    800A   D0 02      BNE $800E
    800C   30 42      BMI $8050
    800E   A5 03      LDA $03
    8010   C9 01      CMP #$01
    8012   F0 3C      BEQ $8050

; if-endif ( else supported )

    * = 8000   
   
    foo = $00
    bar = $01
    baz = $03
   
    if (  !( bar & #$03 && baz == N set ) || (( V set || baz < #$10 ) || foo = #1) )
        nop
    endif

    ; code output:
    8000   A5 01      LDA $01
    8002   29 03      AND #$03
    8004   F0 12      BEQ $8018
    8006   A5 03      LDA $03
    8008   10 0E      BPL $8018
    800A   70 0C      BVS $8018
    800C   A5 03      LDA $03
    800E   C9 10      CMP #$10
    8010   90 06      BCC $8018
    8012   A5 00      LDA $00
    8014   C9 01      CMP #$01
    8016   D0 01      BNE $8019
    8018   EA         NOP
    8019
Re: IF macro for ca65
by on (#119771)
Quick note: Added for-next style loop. Nestable.

1)C-style of loop:
for ( <thing to do 1st>, <Flag to test - continue while true >, <stuff to do at end of loop> )

Example:

Code:
for ( x := #$3, not negative, dex )
; code
next

; more complex:

for ( x := foo, (x > #10) && (foo <> #1), dex:dex)
    ; some code
next


2) BASIC-style syntax:

This actually tries to optimize some, and will break if you mess with your counter register or variable without thinking:

Code:
for x := #$AA to #$10 step -3
    ;some code
next


It will loop until your counter hits the first invalid (for the loop) value. If possible it will skip CMP and use BPL/BMI or a lone BNE. 'step' can be omitted and a step of -1 or 1 decided on if possible. You can use variables rather than immediate values, but no optimizations are possible.

https://www.assembla.com/code/ca65hl/git/nodes/devel

Next is to fix 'elseif'.
Re: IF macro for ca65
by on (#119810)
Nested 'elseif' seems to be working properly: (random nonsense code)

Image
Re: IF macro for ca65
by on (#119864)
Looks interestingly. Will be great to watch video as everything works.
Re: Please Help me Understand This Schematic Portion
by on (#119870)
Are you saying you would like to see a video? What specifically would you like to see in a video on this topic?
Re: IF macro for ca65
by on (#119990)
Movax12 wrote:
What specifically would you like to see in a video on this topic?

Nothing specifically, just want to understand
How macro operators work. And how you can use operators in disassembler. This only works in Mario Disasm, or it can be used with any disassembler?
Anyway thanks.
Re: IF macro for ca65
by on (#119991)
This works with the assembler (ca65). I'm really not sure where I would start with a video, or if this topic really lends itself well to a video. Perhaps someday I'll make a video of something. The wiki here explains how the macros work, but the latest information in this thread is not documented in the wiki just yet.
Re: IF macro for ca65
by on (#119994)
I still harbor fantasies of this becoming more like batari BASIC. I think "all" it would take is a canned kernel to update the screen and some functions for tiles, sprites, input and sound.

End users would still have to make sure not to use up too many cycles but that's life.
Re: IF macro for ca65
by on (#119995)
But Atari, despite being harder to make stuff for, is sumpler in what it is needed to do and such. I don't think you'd be able to make anything scrolling/map-updating+sound+sprites with a little basic thingy. Maybe if you made it work on modules, that'd be cool to try out.
Re: IF macro for ca65
by on (#119996)
3gengames wrote:
But Atari, despite being harder to make stuff for, is sumpler in what it is needed to do and such. I don't think you'd be able to make anything scrolling/map-updating+sound+sprites with a little basic thingy. Maybe if you made it work on modules, that'd be cool to try out.


Yeah. batari BASIC does work in the way you just described. It has different canned kernels for a specific set of needs.

set kernel_options pfheights pfcolors
(use the canned kernel that has adjustable playfield heights & colors)

would give you a different game engine than

set kernel_options pfheights playercolors
(use kernel that allows adjustable playfield height and the first sprite can have multiple colors)


Likewise I'd imagine an NES version would have different kernels whether you want single screen games using no MMC or side-scrolling using MMC1.
Re: Please Help me Understand This Schematic Portion
by on (#119997)
I have all kinds of modular stuff going on for my game project. I have a global config file that has a bunch of options that can vastly change what is output. This part of the project stands on its own though, and I like the fact it doesn't need any library code or memory on it's own. I do imagine that I would release the rest of my ideas and some library stuff at some point, which may be closer to batari BASIC. The flexibility of the syntax with ca65hl is already much more developed however.
Re: Please Help me Understand This Schematic Portion
by on (#119998)
Movax12 wrote:
I have all kinds of modular stuff going on for my game project. I have a global config file that has a bunch of options that can vastly change what is output. This part of the project stands on its own though, and I like the fact it doesn't need any library code or memory on it's own. I do imagine that I would release the rest of my ideas and some library stuff at some point, which may be closer to batari BASIC. The flexibility of the syntax with ca65hl is already much more developed however.


Are you familiar with NESHLA?
http://neshla.sourceforge.net/

Does this project compare with that (as far as results not implementation)?.
Re: IF macro for ca65
by on (#120001)
Odd that the sub-subject header is wrong on the last two posts.. forum bug?

Anyway, yes, read the 1st post, I used to use NESHLA. I would consider the abilities of ca65hl to be comparable but more advanced.
Re: IF macro for ca65
by on (#120005)
Movax12 wrote:
Odd that the sub-subject header is wrong on the last two posts.. forum bug?

If you push the quote button, phpBB 3 copies the quoted post's subject into your post's subject. Otherwise, it copies the first post's current subject (which the Subject Fairy may have since edited) into your post's subject. If you click quote, delete the entire quoted post, and write something else entirely, your post still gets the quoted post's subject.
Re: IF macro for ca65
by on (#120995)
Could you make some kind of central site with all of your code? Tried to find something on your blog, but it is mixed with disassembly of SMB and whatnot. Also your code formatting makes my eyes hurt (hint: using blue color for background, white for keywords and yellow for code works only in 80x25 terminal that uses DOS font, in 320x240, on anything different it just hurt people's eyes). Anyway, since I'm learning NES assembly now (with ca65), your macro will be useful for me.

by on (#120997)
Check page 3 of this thread for the assembla link. Check out the wiki. Sorry you don't like the colors, my eyes like it.
Re: IF macro for ca65
by on (#121002)
Thanks! Have a :beer: on me!

Anyway, since you are pretty knowledgeable, could you do some macros for following things:
- Setting tile ID in nametable at specific x,y, so I can plot tiles onto nametable (very important if you are going to make something more advanced than scrolling static screen)
- Plotting 16-bit numbers on screen for things like score, etc. (as decimals)

I won't mislead you: I am quite noob (yet) when it comes to NES development and this would give me boost I need to explore this further.
Re: IF macro for ca65
by on (#121006)
darkhog, as a beginner NES software developer, you'd really better to forget about macros for now, until you learn some 6502 assembly and the NES HW basics (memory map, at least), maybe by reading through the Nerdy Nights. These two things you asking aren't how the things on the NES works. Setting up a VRAM address or a RAM pointer to given x,y with a macro could work, but it'll lead to inefficient code, forcing you to provide x,y in a specific, not-so-optimal way. Displaying score with a macro is just nonsense, it should be done with a subroutine instead, because macro will duplicate the (not so short) code at every call, which will give program memory overhead for near-zero CPU speed gain. Not to mention that there are many ways to display score, each one has its specifics and should be used accordingly.
Re: IF macro for ca65
by on (#121011)
Shiru wrote:
darkhog, as a beginner NES software developer, you'd really better to forget about macros for now, until you learn some 6502 assembly and the NES HW basics (memory map, at least), maybe by reading through the Nerdy Nights. These two things you asking aren't how the things on the NES works. Setting up a VRAM address or a RAM pointer to given x,y with a macro could work, but it'll lead to inefficient code, forcing you to provide x,y in a specific, not-so-optimal way. Displaying score with a macro is just nonsense, it should be done with a subroutine instead, because macro will duplicate the (not so short) code at every call, which will give program memory overhead for near-zero CPU speed gain. Not to mention that there are many ways to display score, each one has its specifics and should be used accordingly.

Then as subroutines, geez...

Also for setting specific tile on specific x/y I was thinking about stuff like that:

Code:
;store previous values of registers
sta zp_tempa
stx zp_tempx
sty zp_tempy
lda #$3b ; load tile to put on tilemap
ldx #5 ;load x of tile
ldy #5 ; load y of tile
jsr place_tile
;restoring old values of registers:
lda zp_tempa
ldx zp_tempx
ldy zp_tempy


Without routine like that making discrete changes to nametable such as putting score, updating lifebars, etc. is impossible if you don't want to update whole nametable.

Also I was using displaying score as example. Another one may be displaying current level number, etc. - anything that involves displaying decimal 16bit number on screen. I just want general routine to display decimal numbers, that's all.
Re: IF macro for ca65
by on (#121015)
To translate a 16-bit number from binary to decimal, you could use this subroutine that takes about 700 cycles (6 scanlines) to get the digits, and then you could make another subroutine that runs during vblank and prints the digits to the screen. In my current project, there are four steps: get the digits, convert them to an ASCII string, render the string to tiles, and copy the tiles to the screen.
Re: IF macro for ca65
by on (#121016)
Well, macros vs subrotines is not 'geez', they are competely different things, related to different entities (specific translator vs CPU). This difference means that you are asking a random guy who is good is in making macros for cc65 in a thread about macros for cc65 to give you some random code, i.e. you are asking to do completely different thing.

If you are understand how the NES video hardware workds, you should understand that setting a tile in a nametable is not so straightforward thing. If your nametable is just 1024 bytes in the main RAM, it is one thing. If it is in the VRAM (actual nametable), and the rendering is disabled, it is another. If you need to update tiles when rendering is enabled (your case, as you have mentioned scrolling), this is a whole range of different things: updating sequences of random tiles, updating columns or rows, updating only tiles or attributes, etc, etc, etc. A lot of things should be considered to provide some solution to the task. It can't be as simple as 'please make me a macro', it is a whole topic to be discussed, with certain level of knowledge considered (about the HW, about your specific needs, etc).
Re: IF macro for ca65
by on (#121031)
darkhog, I'm more than happy to help you with a specific macro question if you would like, but macros aren't subroutines, though they can call subroutines, it's not the same thing.

Writing a macro to do some nametable functions is doable, but, as Shiru says, there are many different things that need to be considered, and such a macro would have to be very generic with lots of options to suit different uses, or very specific to what is needed at the time.

If your macro was writing to a vram buffer, for example, you still need to have a separate routine to copy that data to screen when NMI was triggered.

Think of a macro as a routine that is called when assembling the code, that outputs 6502 assembly, or other macros until only 6502 assembly is left. The assembler then assembles that code. The macro can not eliminate actually writing the code.