VBCC Optimizing C-compiler now supports NES

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

User avatar
Banshaku
Posts: 2377
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: VBCC Optimizing C-compiler now supports NES

Post by Banshaku » Thu Jul 16, 2020 3:14 pm

Regarging main, no problem, seems to work fine. As for constructors/destructors, are they really necessary? There seems to be 2 segments for that.
vbc wrote:
Thu Jul 16, 2020 10:12 am
To use automated banking with another mapper, you probably have to adapt the bank*.s functions to use another switching mechanism. The chapter on banking in the 6502 section of the vbcc documentation lists the functionality needed.
I found the part in the ABI and may need to ask questions later to lazycow to understand how it works if I want to get far pointer working again. For now it's not a big issue but will figure out later. As for data, usually in a nes game with a lot of data, music etc, you need to change many time the banks during one frame because of lack of space so this is usually done in asm before accessing the data.

vbc wrote:
Thu Jul 16, 2020 10:12 am
No, vbcc generates code only after it has parsed the source and it does not keep the source code in memory. It does keep references to files and line-numbers to be able to generate source-level debug information, but this is not yet available for 6502. I could add a debug option that generates file name and line number as comments in the assembly code, but I am not sure that is too helpful.
No problem then. It may or not be useful, it just while debugging code, having the C code and seeing the asm result what interesting to see if the method was a bottle neck or not but I guess the asm file created with vbcc should be understandable enough.

vbc wrote:
Thu Jul 16, 2020 10:12 am
You mean instead of a backslash? Does it cause problems? Most make tools seem to work with that whereas backshlash only works on windows.
Here's an example:

Code: Select all

src/main.o: src/main.c src/test//test.h
the object file is not in the destination folder (I will check if it's not an issue with my makefile, just in case) and the header file, which is a dependency, has "//" before the name. That seems a bug to me while generating the path but make may be able to make it work anyway. Just wanted to mention a possible bug in the path generation.
vbc wrote:
Thu Jul 16, 2020 10:12 am
The full library source is not public. Just tell me what you need to know.
For now I may not need it after all since when you remove the data segment, you see which one requires it with the error messages. After I removed the usage of all lib function, the errors stopped. If I have question, I will let you know.

Thank you again for the information, I will continue my sample and may have some question later.

edit:

I have a question regarding the zpage directive since of the way I see it used in the startup files. The way I understand from the doc is that it declare a symbol as zero page. What I want to know is:
- It only needs to be done once, right? It seems to be used like a way to "import" it in file in current startup code, every time it is used
- in startup, there is a special section called zpage without "", which seems to be a system one. Doesn't the compiler automatically promote those symbols to zpage?

Another thing, there is "ezp" but I'm not sure what it is. If it's like EQU, usually it's only a literal value/string which means it shouldn't need to know if zero page related but I think it's more something like "reserve", to declare a symbol that is right a way in zero page without the need to use zpage after. Which one is the actual usage?

edit2:

I'm debugging my converted code and I think I found a bug with a new feature in 6502 in vasm. If you use the option "-dotdir", it works but not for zpage and you have to define it without the dot. If not:

Code: Select all

error 2 in line 12 of "libs/vbcc/vbcc_zpage.s": unknown mnemonic <.zpage>
	included from line 5 of "src/crt0/startup.s"

rox_midge
Posts: 88
Joined: Mon Sep 19, 2005 11:51 am

Re: VBCC Optimizing C-compiler now supports NES

Post by rox_midge » Fri Jul 17, 2020 6:35 am

How do you get VBCC to use register parameters? The way I'd been writing my assembly code was to use a specific zero-page variable as the parameter location and just call the function without messing about with the stack. The documentation seems like VBCC supports this, but every time I try to use it, I just get 'unknown register "a"'.

The documentation also specifically says that this could result in worse code; is there a way to get VBCC to auto-select a zero-page variable to use as a parameter?

User avatar
Banshaku
Posts: 2377
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: VBCC Optimizing C-compiler now supports NES

Post by Banshaku » Fri Jul 17, 2020 7:05 am

rox_midge wrote:
Fri Jul 17, 2020 6:35 am
How do you get VBCC to use register parameters? The way I'd been writing my assembly code was to use a specific zero-page variable as the parameter location and just call the function without messing about with the stack. The documentation seems like VBCC supports this, but every time I try to use it, I just get 'unknown register "a"'.
I was able to test it a few minutes ago and I used as a reference the example in the lazynes code header. Here's an example when you pass an adress:

Code: Select all

void loadPalette(__reg("a/x") const char *palette);
It tells the compiler that the adress will be passed in a/x registers.

Then it can be used that way in asm code:

Code: Select all

_loadPalette:
    sta zpTemp
    stx zpTemp+1
    
    ldy #0                          ; index for src/dst
    ldx #$20                        ; counter
    
    sty zpPaletteUpdateFlag         ; disable palette updating

.load:
    lda (zpTemp),y
    sta palBuffer,y
    iny
    dex
    bne .load

    inc zpPaletteUpdateFlag         ; set flag to update palette
    
    rts
once I set the register, it started to work the same way was cc65 when passing parameters. I saw in other examples that zero pages variables were set the same wway like in the lazynes header example:

Code: Select all

void lnPush(__reg("a/x") uword o, __reg("r0") ubyte a, __reg("r2/r3") void* s);

vbc
Posts: 40
Joined: Sun Jun 21, 2020 5:03 pm

Re: VBCC Optimizing C-compiler now supports NES

Post by vbc » Fri Jul 17, 2020 8:15 am

Banshaku wrote:
Thu Jul 16, 2020 3:14 pm
Regarging main, no problem, seems to work fine. As for constructors/destructors, are they really necessary? There seems to be 2 segments for that.
Constructors/destructors are used by some library functions, e.g. to close all opened files on exit. It is very unlikely that you will need them for a NES game.
I have a question regarding the zpage directive since of the way I see it used in the startup files. The way I understand from the doc is that it declare a symbol as zero page. What I want to know is:
- It only needs to be done once, right? It seems to be used like a way to "import" it in file in current startup code, every time it is used
- in startup, there is a special section called zpage without "", which seems to be a system one. Doesn't the compiler automatically promote those symbols to zpage?
The zpage section is just a normal section. It is put into zero page by the linker script, but to the assembler it is in no way special. Therefore the zpage directive is used to instruct vasm to use the shorter zero-page addressing wherever this symbol is used. The code would also work without it, but it would be larger.

It has to be present once for each symbol used in each assembly source file to create best code.
Another thing, there is "ezp" but I'm not sure what it is. If it's like EQU, usually it's only a literal value/string which means it shouldn't need to know if zero page related but I think it's more something like "reserve", to declare a symbol that is right a way in zero page without the need to use zpage after. Which one is the actual usage?
I did not implement this feature, so I have to ask Frank about it to be sure. But it does work like equ and I presume that it is useful for a 65C02 where you can move the zero page window.
I'm debugging my converted code and I think I found a bug with a new feature in 6502 in vasm. If you use the option "-dotdir", it works but not for zpage and you have to define it without the dot. If not:
-dotdir is an option of the syntax module and affects only the directives of the syntax module. zpage is provided by the 6502 backend and therefore not affected by -dotdir.

vbc
Posts: 40
Joined: Sun Jun 21, 2020 5:03 pm

Re: VBCC Optimizing C-compiler now supports NES

Post by vbc » Fri Jul 17, 2020 8:22 am

rox_midge wrote:
Fri Jul 17, 2020 6:35 am
How do you get VBCC to use register parameters? The way I'd been writing my assembly code was to use a specific zero-page variable as the parameter location and just call the function without messing about with the stack.
This is vbcc's default calling convention. It will use several zero page registers to pass the first arguments. You can also override the default registers using __reg().
The documentation seems like VBCC supports this, but every time I try to use it, I just get 'unknown register "a"'.
Can you give an example? This should work:

Code: Select all

volker@y50:/tmp$ cat sc.c
void myfunc(__reg("a") char);
void f()
{
  myfunc(123);
}
volker@y50:/tmp$ vc +nrom256v -S -O sc.c
volker@y50:/tmp$ head sc.asm 
;vcprmin=10000
        section text
        global  _f
_f:
        lda     #123
        jmp     _myfunc
; stacksize=0+??
        global  _myfunc
The documentation also specifically says that this could result in worse code; is there a way to get VBCC to auto-select a zero-page variable to use as a parameter?
This is the default behaviour:

Code: Select all


volker@y50:/tmp$ cat sc.c
void myfunc(char,char,char);
void f()
{
  myfunc(1,2,3);
}
volker@y50:/tmp$ vc +nrom256v -S -O sc.c
volker@y50:/tmp$ head sc.asm -n 15
;vcprmin=10000
        section text
        global  _f
_f:
        lda     #1
        sta     r0
        lda     #2
        sta     r2
        lda     #3
        sta     r4
        jmp     _myfunc
; stacksize=0+??
        global  _myfunc
        [/quote]

User avatar
Banshaku
Posts: 2377
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: VBCC Optimizing C-compiler now supports NES

Post by Banshaku » Fri Jul 17, 2020 9:16 am

My second sample is now working fine and is:
- not using libvc, to test if works fine nes only or not
- removed ctor/dtor and no issue, like you said
- uses my own init code in startup
- uses custom nmi changable at runtime

It is progressing well. If I could have the symbols in mesen that would be great but for now I'm more than fine. Maybe there is a way to extract them from the map, will check later if something can be done for mesen put priority is low (mmc3 is first priority and porting code second).
vbc wrote:
Fri Jul 17, 2020 8:15 am
The zpage section is just a normal section. It is put into zero page by the linker script, but to the assembler it is in no way special. Therefore the zpage directive is used to instruct vasm to use the shorter zero-page addressing wherever this symbol is used. The code would also work without it, but it would be larger.

It has to be present once for each symbol used in each assembly source file to create best code.
Regarding the section, understood. It would be great to define a section as "zp" so you wouldn't have to set zp on every of them (like the xwr arguments). That could be an interesting option in the future.

As for zpage for declaring a symbol zp friendly, I'm not sure I understand your answer unfortunately. For example, let say I have r0 defined in startup. Then I "promote" it to zero page in that module. I decide to use r0 in nmi.s. Do I have to say again in nmi.s that r0 is zpage or like global, as long as you do it once, it will be fine? This is the part I'm not sure.

For ezp, undersood. Maybe I should check the source code, it may show some detail about it.
vbc wrote:
Fri Jul 17, 2020 8:15 am
-dotdir is an option of the syntax module and affects only the directives of the syntax module. zpage is provided by the 6502 backend and therefore not affected by -dotdir.
Now that I understand how it work in the background, ok, but still, from a usability point of view, I would have expected that if I put -dotdir on vasm, it would have worked up to the layer of 6502 since from a user point of view I'm using VASM and not aware of those inner separation. It would be nice to add that dot zpage later too ;)

I will continue to experiment with it. I think it is going well I should be able to port more and more code. Only one bug with deps, other ones were just settings missing. Should be able to experiment with mmc3 soon.

One last question, I see in vasm doc old style, standard style. I think I'm using the old one but what I'm curious about is how does it work with 6502 and what would have gain from using the standard one, if that is even possible?

Thank you again for all the information, always appreciated.

vbc
Posts: 40
Joined: Sun Jun 21, 2020 5:03 pm

Re: VBCC Optimizing C-compiler now supports NES

Post by vbc » Fri Jul 17, 2020 1:45 pm

Banshaku wrote:
Fri Jul 17, 2020 9:16 am
My second sample is now working fine and is:
- not using libvc, to test if works fine nes only or not
- removed ctor/dtor and no issue, like you said
- uses my own init code in startup
- uses custom nmi changable at runtime

It is progressing well.
Sounds good.
If I could have the symbols in mesen that would be great but for now I'm more than fine. Maybe there is a way to extract them from the map, will check later if something can be done for mesen put priority is low (mmc3 is first priority and porting code second).
vlink can also generate a label list usable by the vice C64 emulator (option -vicelabels). Perhaps this file is easier to convert than the mapfile.
As for zpage for declaring a symbol zp friendly, I'm not sure I understand your answer unfortunately. For example, let say I have r0 defined in startup. Then I "promote" it to zero page in that module. I decide to use r0 in nmi.s. Do I have to say again in nmi.s that r0 is zpage or like global, as long as you do it once, it will be fine? This is the part I'm not sure.
You have to use the zpage directive again in nmi.s. Otherwise there is no way for vasm to know that the symbol is in zero page.
I will continue to experiment with it. I think it is going well I should be able to port more and more code. Only one bug with deps, other ones were just settings missing. Should be able to experiment with mmc3 soon.
Glad to hear that.
One last question, I see in vasm doc old style, standard style. I think I'm using the old one but what I'm curious about is how does it work with 6502 and what would have gain from using the standard one, if that is even possible?
The various syntax modules provide different syntax for the directives, macros, etc. but they are very similar in functionality. They are mostly there to provide compatibility with existing code or assemblers on different platforms. For example, assemblers for the PowerPC will usually use the standard syntax, on the 68k mot as well as std are commonly used, etc.

It is possible to build vasm for 6502 using the standard syntax module (it is not a runtime option), but I don't think this syntax is really used anywhere on the 6502. It is just different. I don't think you would gain anything by using it.

tepples
Posts: 22017
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: VBCC Optimizing C-compiler now supports NES

Post by tepples » Fri Jul 17, 2020 5:04 pm

vbc wrote:
Thu Jul 16, 2020 10:12 am
The full library source is not public. Just tell me what you need to know.
I would like to know
  1. under what conditions a user of vbcc is allowed to include portions of the library in a program distributed to the public, and
  2. under what conditions a user of vbcc is allowed to take self-help steps to understand how the library works, especially while you are on vacation or otherwise unavailable. (Bus factor.)

rox_midge
Posts: 88
Joined: Mon Sep 19, 2005 11:51 am

Re: VBCC Optimizing C-compiler now supports NES

Post by rox_midge » Fri Jul 17, 2020 5:18 pm

vbc wrote:
Fri Jul 17, 2020 8:22 am
rox_midge wrote:
Fri Jul 17, 2020 6:35 am
The documentation also specifically says that this could result in worse code; is there a way to get VBCC to auto-select a zero-page variable to use as a parameter?
This is the default behaviour:
Ah! I was trying to invoke 'vbcc6502' directly, which spits out code that uses the stack. Using 'vc' instead along with a config file does work exactly as described.

It's working well now, thanks!

User avatar
Banshaku
Posts: 2377
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: VBCC Optimizing C-compiler now supports NES

Post by Banshaku » Fri Jul 17, 2020 5:33 pm

rox_midge wrote:
Fri Jul 17, 2020 5:18 pm
Ah! I was trying to invoke 'vbcc6502' directly, which spits out code that uses the stack. Using 'vc' instead along with a config file does work exactly as described.

It's working well now, thanks!
I'm calling vbcc6502 directly and passing parameters with registers is working well with my makefile so it should have worked. If you are curious to know how to use it directly, try to compile with vc -vv and it will show you all the parameters it used. Maybe one of them was missing. Still, if for you vc does the job then calling directly is maybe not necessary since some parameters are not the same and VC frontend take care of them (-O is an example of the one that differ).

Vbc should be able to give more detail on the subject if the need arise, I'm still learning it ^-^;;

User avatar
Banshaku
Posts: 2377
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: VBCC Optimizing C-compiler now supports NES

Post by Banshaku » Fri Jul 17, 2020 6:01 pm

Regarding zpage, understood, I will now define them everywhere they are used. I will reread it again, maybe it's a misunderstanding since I'm not English native but the doc doesn't make it clear that you have to mark it in every module and I went with the assumption that it should work like global.

The way it works with cc65 is that zeropage is a system segment (section) that promote those variable to zero page automatically (it cause other issue that zp was locked at 0000 and makes problems for 6280 but vasm doesn't have this issue). You still have to export/import them in every module with exportzp/importzp. When you think about it, I guess to some degree they are similar since you need a special export/import for them.

Regarding the vice label, yes, that should be a lot easier to parse than the map file so I should look into this. I will ask Sour if there is a simple way to convert a vice file to make it compatible with mesen. Even just for the asm symbols, that would already help a lot.
vbc wrote:
Fri Jul 17, 2020 1:45 pm
It is possible to build vasm for 6502 using the standard syntax module (it is not a runtime option), but I don't think this syntax is really used anywhere on the 6502. It is just different. I don't think you would gain anything by using it.
Since it's not a runtime option and I would need to build it, well, I was able to port some code to old style so I guess I should be fine. I started to code 6502 for nes as a hobby so I know mostly what newer assembler uses so I was hoping that maybe some thing would have been different or more similar to what I used recently (the dot notation is one example). I will read the doc for standard syntax, out of curiosity, since I may use later vasm for other platform if the need arise.

vbc
Posts: 40
Joined: Sun Jun 21, 2020 5:03 pm

Re: VBCC Optimizing C-compiler now supports NES

Post by vbc » Sat Jul 18, 2020 3:48 am

tepples wrote:
Fri Jul 17, 2020 5:04 pm
under what conditions a user of vbcc is allowed to include portions of the library in a program distributed to the public, and
For non-commercial use you can include it without restrictions. For commercial use of vbcc please contact me.
under what conditions a user of vbcc is allowed to take self-help steps to understand how the library works, especially while you are on vacation or otherwise unavailable. (Bus factor.)
I am not sure what you mean by "self-help", but I do not think I have any problems here. It is also easy to link with another library and/or overwrite parts of the library with your own functions.

Oh, and I try to look both ways before I cross the street. :-)

User avatar
Banshaku
Posts: 2377
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: VBCC Optimizing C-compiler now supports NES

Post by Banshaku » Sat Jul 18, 2020 9:00 am

I was able to finish phase 2 which is:
- test with NROM256
- understand how linker script work and adapts to own need
- learn more about linker

I simplified a few things in the linker but had to add more things in the makefile since I now spit all (prg/chr/header) and build them back in the end. This way, you have prg/chr ready if you need to test with a devcart.

One thing, it would be nice if later for the linker if ORIGIN and LENGTH would be available. If I had those function, I could have extracted some parameters from MEMORY and avoid to hardcode the end of a section. Still, I figured out a simple way that works for nrom, now I need to check if I can make something simple for mmc3.

Until the deps bug is corrected, I just added some sed that add the missing part to the file after being generated and it's now working properly.

Oziphantom
Posts: 859
Joined: Tue Feb 07, 2017 2:03 am

Re: VBCC Optimizing C-compiler now supports NES

Post by Oziphantom » Sun Jul 19, 2020 12:24 am

vbc wrote:
Fri Jul 17, 2020 8:15 am
I did not implement this feature, so I have to ask Frank about it to be sure. But it does work like equ and I presume that it is useful for a 65C02 where you can move the zero page window.
The 65C02 can not move the ZP. You might be thinking of the 65816 which can move the DP and SP to anywhere in the first 64K bank. Or the 65CE02 which sadly nobody actually can get their hands on.
However on the Commodore 128 which runs a N6502 core, you can move the ZP and the SP to anywhere in the 128K and it also swaps the addresses back. So for example if you move the ZP to $1000
sta $2 ; this writes to $0:1002
sta $1002 ; this writes to $0:0002

vbc
Posts: 40
Joined: Sun Jun 21, 2020 5:03 pm

Re: VBCC Optimizing C-compiler now supports NES

Post by vbc » Sun Jul 19, 2020 4:05 am

Banshaku wrote:
Sat Jul 18, 2020 9:00 am
One thing, it would be nice if later for the linker if ORIGIN and LENGTH would be available.
What should they do? How would they differ from ADDR and SIZEOF?

Post Reply