Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in 
CSDb User Forums


Forums > C64 Coding > Badass - New 6502 Assembler
2020-06-28 17:47
Sasq

Registered: Apr 2004
Posts: 106
Badass - New 6502 Assembler

The last couple of months I've created a new 6502 Assembler called bass (or Badass).

The basic idea is for it to be as advanced as Kickassembler, but with a less complex, more unified syntax.

And it also has unit tests in an internal emulator.

You can find it at https://github.com/sasq64/bass

I've started a tutorial here: http://apone.org/bass/part1.html

Here is an example C64 source http://apone.org/bass/example.asm.html
2020-06-28 18:03
Frantic

Registered: Mar 2003
Posts: 1432
Looks quite nice at first glance!
2020-06-28 19:58
Groepaz

Registered: Dec 2001
Posts: 9317
This is really interesting!
2020-06-28 20:29
Bacchus

Registered: Jan 2002
Posts: 124
Interesting. Will have a look.

/Bacchus
2020-06-28 21:04
Sasq

Registered: Apr 2004
Posts: 106
Some other things:

* It should be pretty easy to build, you just need a modern C++ compiler and CMake. Windows users can open the directory in VS Code for instance.

* If you're looking to customize the assembler it should also be straight-forward. Look in `meta.cpp` for the definitions of all meta commands and `functions.cpp` for functions. You should be able to add your own by copying the existing ones.


The thing I'm experimenting most with now is how to interact with the emulator. You can for instance call into LUA from 6502 using "brk", and this could be used for proto-typing -- ie to start with LUA code and then re-implement it in 6502 with tests to back it up.

I also modified the X16 Commander emulator to also bind LUA to 6502 in the same way so I can run X16 programs that are partly in LUA.

Unit tests are also good for optimizing, since you get the cycle count as an output, so you can assert that your code does not become slower.
2020-06-28 21:10
JackAsser

Registered: Jun 2002
Posts: 1680
I must say I'm impressed by your C++ coding style. Really a pleasure to the eye. And also a nice project with a lot of new ideas.

To me personally I always use Eye of the Beholder as a test case in my head; could I port EotB to this assembler? And by the looks of it, no, due to the lack of high level memory management with segments and separate linking and so on. Maybe features to add for someone?
2020-06-28 21:16
Sasq

Registered: Apr 2004
Posts: 106
I am looking for beta testers, so there is a good chance I will implement any required features for someone actively using it :)

And I am aware that there is functionality missing in memory layout, sections and linking. I am not sure exactly how to make that powerful and simple.

Right now you can for instance do things like this:
!section "extra", sections.main.end

; stuff

!section "main", $801

; more stuff


This will place section "extra" after "main".

... but I realize you need something more advanced. Suggestions are welcome.
2020-06-28 21:20
Krill

Registered: Apr 2002
Posts: 1475
Some great ideas and modern approaches to old problems.

One thing i've occasionally missed with 6502 assemblers is the possibility to have a hashbang in the first line of an assembly source file.

I like to have small projects (size-restricted demos mostly, or random experiments) in single monolithic files, and avoiding to create a build script or Makefile when getting started on something new would be nice. :)
2020-06-28 21:24
JackAsser

Registered: Jun 2002
Posts: 1680
Quote: Some great ideas and modern approaches to old problems.

One thing i've occasionally missed with 6502 assemblers is the possibility to have a hashbang in the first line of an assembly source file.

I like to have small projects (size-restricted demos mostly, or random experiments) in single monolithic files, and avoiding to create a build script or Makefile when getting started on something new would be nice. :)


hashbangs are implemented by the exec() routine in the OS..
2020-06-28 21:24
Krill

Registered: Apr 2002
Posts: 1475
As for sections and the like, have you checked out 64tass?

This is my current go-to assembler for smaller projects, and seems quite similar in its approaches.

Full-blown separate link stage is ca65's domain, of course, but i usually avoid linker files until they really make things tidier and more managable, which happens rather late for most projects.
2020-06-28 21:25
Krill

Registered: Apr 2002
Posts: 1475
Quoting JackAsser
hashbangs are implemented by the exec() routine in the OS..
Until the interpreter in question chokes on a syntax error. :)
2020-06-28 21:28
Sasq

Registered: Apr 2004
Posts: 106
@Krill: Done :)

(Just extended the grammar to allow '#' comments if they are whole line comments).
2020-06-28 21:31
Krill

Registered: Apr 2002
Posts: 1475
Awesome! \=D/
2020-06-28 21:32
Sasq

Registered: Apr 2004
Posts: 106
My "vague" plan about sections and linking is not to have linking, but rather something more "javascript" like where you can have sources that "export" symbols and then you can import those sources.

And instead of a link script you can choose to have a top level source file that lays out everything.
2020-06-28 21:33
JackAsser

Registered: Jun 2002
Posts: 1680
Quote: @Krill: Done :)

(Just extended the grammar to allow '#' comments if they are whole line comments).


Ahh, that little detail!
2020-06-28 21:34
JackAsser

Registered: Jun 2002
Posts: 1680
Quote: My "vague" plan about sections and linking is not to have linking, but rather something more "javascript" like where you can have sources that "export" symbols and then you can import those sources.

And instead of a link script you can choose to have a top level source file that lays out everything.


I can do a small write up what I personally would need in terms of segments to support building a complex cart like EotB. I had similar chats with Mads when he implemented segments in Kickasm.
2020-06-28 21:36
Sasq

Registered: Apr 2004
Posts: 106
Quote: I can do a small write up what I personally would need in terms of segments to support building a complex cart like EotB. I had similar chats with Mads when he implemented segments in Kickasm.

That would be great!
2020-06-28 21:36
Krill

Registered: Apr 2002
Posts: 1475
Quoting Sasq
My "vague" plan about sections and linking is not to have linking, but rather something more "javascript" like where you can have sources that "export" symbols and then you can import those sources.

And instead of a link script you can choose to have a top level source file that lays out everything.
Sounds like this could be achieved with separate section-declare/collect and section directives, as 64tass does.

These allow the position in the source code to be independent of the position in the output binary.

Rest (splitting up source files) can be done via regular include semantics.
2020-06-28 21:45
JackAsser

Registered: Jun 2002
Posts: 1680
Quote: Quoting Sasq
My "vague" plan about sections and linking is not to have linking, but rather something more "javascript" like where you can have sources that "export" symbols and then you can import those sources.

And instead of a link script you can choose to have a top level source file that lays out everything.
Sounds like this could be achieved with separate section-declare/collect and section directives, as 64tass does.

These allow the position in the source code to be independent of the position in the output binary.

Rest (splitting up source files) can be done via regular include semantics.


It's not only that. It's more about the assembler needs to know the bank ID for all labels it has so that bank switch macros knows what bank to switch in when JSRing (via ram trampolines) across different banks.

ca65 solves this by allowing an arbitrary bank-id to be assigned to a memory-directive. Segments emitting code into that memory will have all their labels assigned with that bank ID and other code can resolve it with the .bank(label) operator.
2020-06-28 21:48
Krill

Registered: Apr 2002
Posts: 1475
Would a .sectionof(label) directive allow for that? Sections are named, of course.
2020-06-28 21:53
JackAsser

Registered: Jun 2002
Posts: 1680
Quote: Would a .sectionof(label) directive allow for that? Sections are named, of course.

Yes, maybe. Bottom line I have a jsrf (jsr far) macro that works and looks exactly like jsr but the assembler emits all the code needed to perform a proper bankswitch and back again upon rts. This gives me the freedom to shuffle around the segments completely across various banks without having to think about it. That makes it very easy for me to fill the banks and pack the code tightly and never worry about breaking code when shuffling around the segments onto other banks.
2020-06-28 22:02
Sasq

Registered: Apr 2004
Posts: 106
Could this be supported by simply allowing > 16bit addresses in symbols ? Meaning normally the top 8bits of a 24bit address would be the bank.

So then something like

!macro jsrf(a)
  lda #a>>16 ; load bank
  ; Do magic
  jsr a ; (top bits ignored as normal)
}

!section "bank5", $05a000
my_code:
   nop
   rts
!section "bank6", $06a000
   nop
   jsrf my_code
2020-06-28 22:12
JackAsser

Registered: Jun 2002
Posts: 1680
Quote: Could this be supported by simply allowing > 16bit addresses in symbols ? Meaning normally the top 8bits of a 24bit address would be the bank.

So then something like

!macro jsrf(a)
  lda #a>>16 ; load bank
  ; Do magic
  jsr a ; (top bits ignored as normal)
}

!section "bank5", $05a000
my_code:
   nop
   rts
!section "bank6", $06a000
   nop
   jsrf my_code


That a step closer indeed. Also, sections needs to be filled and padded out so that the final binary have all the segments after each other. So you typically need a size and a fillval parameter for each section also. You also need to specify run-adress, in this case $8000 for both segments.

Also declaring a section with the same name further down but without adress should ideally continue to fill the section with "stuff". I use this f.e. to put bits and pieces of the clear frame buffer unrolled code where there is room. All of a sudden a bank is filled and a small portion of this clear code has to be moved to another section, so I just change the bank-id (or in your case section name) to something else and see if it fits there.

But all of this are just curiosities. I will NOT port EotB to this assembler, but just wanted to share the more advanced use cases with banking and segments.
2020-06-28 22:29
Sasq

Registered: Apr 2004
Posts: 106
Quoting JackAsser
T
But all of this are just curiosities. I will NOT port EotB to this assembler, but just wanted to share the more advanced use cases with banking and segments.


EoTB must be one of the largest C64 projects ever, so yeah that would be pretty stupid ;)
2020-06-29 00:22
Frantic

Registered: Mar 2003
Posts: 1432
Well, good support for cartridge banking is a nice thing to have, regardless of whether the project is super big or not. DreamAss has some features along those lines as well, and I used that at some point for a little cartridge project I was fiddling with. At the moment I am working on a new music editor, and it may eventually turn out that I need to do it as a cartridge image instead, to be able to fit all the stuff that I want to have in it. If that would happen, a great assembler with intuitive support for cartridge banking would surely be my first choice.
2020-06-29 00:56
Krill

Registered: Apr 2002
Posts: 1475
Quoting Frantic
At the moment I am working on a new music editor, and it may eventually turn out that I need to do it as a cartridge image instead, to be able to fit all the stuff that I want to have in it.
Would REU be an option? And if not, Retro Replay's banked 32KB of RAM? :)
2020-06-29 01:03
Frantic

Registered: Mar 2003
Posts: 1432
The way I see it a cartridge image would be a more straightforward solution to the problem at hand, and loading time would be close to zero, even though both of the options you mention would of course provide some more space in different ways. Anyway, a discussion of that would probably be off topic in this thread, and the preferred option is still to squeeze it all into normal C64 RAM if possible.
2020-06-29 10:18
Sasq

Registered: Apr 2004
Posts: 106
@JackAsser: What about this:


stuct Section
    string name
    uint32 start
    uint32 size
    uint32 current_pc
    uint32 offset
    uint8 data[]
    uint32 flags
    uint8 fillchar



ASSEMBLING

* When a section is created, start & current_pc are the same.
* current_pc can be explicitly set, but normally increases as data[] grows.
* Size can be set if known, otherwise it will be the size of the data array.
* Sections can be switched at any time. Generated code and data is appended to the data array of the current section.

* Addresses can be > 16bit. Recommended to use >,< unary operators to get low and high byte.
* Assembler will generate an error if you try to access memory not within the 16bit range (ie where bits 16 and above differ).

OUTPUT

* If offset is not set, offset = start
* If size is not set, size = data.size
* Otherwise grow data to size and insert fillchar
* Write all sections in order to output file at offset

FLAGS

* NoOutput - Section only used for labels and offsets, will not be written to the output file.
* SeparateFile - write section to its own file, based on 'name'.
* ReadOnly - Intended to go into ROM. Assembler could warn if self modifying code is used.

AUTOMATIC BANK HANDLING

* A single section for multiple banks
* Keep track of where bank ends and wrap to next
* Needs grouping of statements so assembler know where it can "bank break"
2020-06-29 10:34
Frantic

Registered: Mar 2003
Posts: 1432
Sounds good I think. Regarding "* ReadOnly - Intended to go into ROM. Assembler could warn if self modifying code is used" it would of course also be important to allow self-modifying code to be assembled to ROM segments, since one would typically copy at least some code from ROM to RAM at runtime, and that code may involve self-modification etc.
2020-06-29 13:32
Golara

Registered: Jan 2018
Posts: 206
big + for c++ I'll definitely check it out
2020-06-29 13:33
JackAsser

Registered: Jun 2002
Posts: 1680
Yes frasse, that is a common use case. I have pure rom segments, i have ram segments (stored on rom) and i have bss-segments (pure ram, nothing stored)
2020-06-29 13:36
Krill

Registered: Apr 2002
Posts: 1475
Quoting Frantic
Sounds good I think. Regarding "* ReadOnly - Intended to go into ROM. Assembler could warn if self modifying code is used" it would of course also be important to allow self-modifying code to be assembled to ROM segments, since one would typically copy at least some code from ROM to RAM at runtime, and that code may involve self-modification etc.
Wouldn't that be a RAM segment that is loaded/assembled to ROM? I.e., a segment with different load and run addresses.
2020-06-29 13:43
Frantic

Registered: Mar 2003
Posts: 1432
Yes, that's what I tried to say. What Jackasser said, basically.
2020-06-29 13:57
Sasq

Registered: Apr 2004
Posts: 106
Well if it's intended for RAM, don't tag it as "Read Only" :)

The terms here can be a bit confusing though.

So if I understand correctly:

load_address is where the section is expected to end up in memory. It is used for checking overlap, and is normally specified directly by the developer. It defines the initial PC (run_address)

run_address is normally the same as load_address, but if the developer changes the PC inside a section, they will not align any more. run_address is something the developer needs to keep track of "manually".

file_offset normally needs to be specified for cart images, where the output is not a simple linear mapping to RAM.
2020-06-29 14:47
Frantic

Registered: Mar 2003
Posts: 1432
Yes, the terms are a bit slippery. So, no matter if I use the terms correctly or not, what I meant was this:

If we distinguish between a segment (a larger unit) and a section (several sections of code can be contained in a segment), a segment which is generally intended for ROM and should be read only, may still contain one section of code which contains something that should be executed in C64 RAM or drive RAM and may contain self-modifying code.

!segment ROM_BANK1, $8000-$A000, READ_ONLY { ;a "segment"

[some read only stuff that can't use self-modifying code etc]

!section NAME_OF_SECTION, relativepc=$0800 { ;a "section" inside the segment

[some stuff that is intended to be copied "manually" from the ROM to $0800 in RAM. This should be able to override the READ ONLY restriction that otherwise applies to the segment that contains this section.]
}

[some more read only stuff that can't use self-modifying code etc]

}

Maybe there is some entirely different and better way to solve this. I just wanted to explain in more detail what I meant.
2020-06-29 16:23
Golara

Registered: Jan 2018
Posts: 206
I know this is tool from coder for a coder, but still you could have released built binaries for people that can't into modern software compilationing

I made it :P Statically linked, so it should work on everything

windows 64bit (compiled with mingw on linux): https://mega.nz/file/2gYXFaBA#MftkFZhFnAdm4fKJ7WCZ4sq3ULVemKlXr..
linux 64bit https://mega.nz/file/2gYXFaBA#MftkFZhFnAdm4fKJ7WCZ4sq3ULVemKlXr..
2020-06-29 16:41
Sasq

Registered: Apr 2004
Posts: 106
@Golara: There are Windows releases on the git-page, built using MSVC.

Binaries for Linux is usually not a good idea.
And for most people it is just "clone" and "make" and you are done.
2020-06-29 16:45
Sasq

Registered: Apr 2004
Posts: 106
@Frantic: I am hoping to avoid multiple levels with both segments and section because it complicates things...

For that particular case you can either mark the section as not ReadOnly and live without the extra checking. But better probably to add support for changing also the ReadOnly state on the fly, like the PC.

I'm wondering if there are other cases that are harder to handle with only one level of sections. Can you think of a situation where you really need the parent/child relationship ?
2020-06-29 16:46
Golara

Registered: Jan 2018
Posts: 206
Quote: @Golara: There are Windows releases on the git-page, built using MSVC.

Binaries for Linux is usually not a good idea.
And for most people it is just "clone" and "make" and you are done.


I must have missed it then. Normaly there's a "releases" tab at the top, next to issues, pull requests etc. But it's not there now...

As for linux binaries. I know what you mean, but these problems arise when you use dynamic linking and your program wants glib 2.14.2 but you have 2.14.1 so it's not compatible :P This is a static build (that's why it's 22mb) and it should work on anything.

The only thing I can see potentially breaking is trying to run this binary on an older kernel than mine... I don't know if that's a problem but if doesn't work my vote is on that.
2020-06-29 16:47
Sasq

Registered: Apr 2004
Posts: 106
@Golara: I think both those links are for the windows build...
2020-06-29 17:06
Frantic

Registered: Mar 2003
Posts: 1432
@sasq: changing the ReadOnly state on the fly sounds like a convenient solution, that doesn't overcomplicate things.

As for other uses of a parent-child type of structure, it is probably not necessary. Benefits of having it, that I can think of, may include:

* Local labels within a "section". If I remember correctly, DASM is pretty strong in this domain. (But you already had something like that in the assembler I think? Some sort of "blocks"? I confess I haven't looked into the details of your assembler yet — so all of what I say is just a bunch of general thoughts based on the discussion in this thread.)

* The grouping of statements that you mentioned, so the assembler knows where to "bank break" (e.g. not in the middle of a section), if you were thinking of some sort of automatic handling of rom banks. In this regard, a "section" could perhaps be defined as "floating", to allow the assembler to place it in any (according to some definition) available space in the ROM banks, rather than necessarily put it where it occurs in the source.

Anyway.. The support for banks/cartridges shouldn't be taken too far. If it comes at the cost of making all kinds of things more complicated in the assembler, it is probably not worth it. Personally I am happy as long as an assembler at least has some basic support for banking/cartridges that makes projects like that a bit easier.
2020-06-29 17:19
Golara

Registered: Jan 2018
Posts: 206
Quote: @Golara: I think both those links are for the windows build...

yes, my bad. Here it is https://mega.nz/file/exYzBCLZ#1KnI4ZkpL-Wk-qtwLkVv1oJtmsw4a_5o0..
2020-06-29 18:19
Oswald

Registered: Apr 2002
Posts: 4584
Quote: Quoting Sasq
My "vague" plan about sections and linking is not to have linking, but rather something more "javascript" like where you can have sources that "export" symbols and then you can import those sources.

And instead of a link script you can choose to have a top level source file that lays out everything.
Sounds like this could be achieved with separate section-declare/collect and section directives, as 64tass does.

These allow the position in the source code to be independent of the position in the output binary.

Rest (splitting up source files) can be done via regular include semantics.


*= allows that aswell, I dont really see advantage of sectons for this :P
2020-06-29 19:34
JackAsser

Registered: Jun 2002
Posts: 1680
Quote: *= allows that aswell, I dont really see advantage of sectons for this :P

Nah. You have position in rom, positioning in ram and positioning in the actual binary (i.e. Bank)
2020-06-29 21:41
Oswald

Registered: Apr 2002
Posts: 4584
Quote: Nah. You have position in rom, positioning in ram and positioning in the actual binary (i.e. Bank)

I mean this part "section-declare/collect and section directives, as 64tass does. These allow the position in the source code to be independent of the position in the output binary."
2020-06-29 21:57
Krill

Registered: Apr 2002
Posts: 1475
Just like chisel and hammer also work to write your next novel, yes.
2020-06-30 05:56
Oswald

Registered: Apr 2002
Posts: 4584
Quote: Just like chisel and hammer also work to write your next novel, yes.

same effor frankly to change section or *= addresses.
2020-06-30 08:34
Krill

Registered: Apr 2002
Posts: 1475
The point is that the current program counter is just one of many attributes of a program section/segment. Once you commit to using them, you have better and more elegant control. Then you also prefer to manipulate section attributes rather than rely on the old blunt tool that is "* =".

And besides, can you easily continue right where some other part of code ended, just by using "* ="? That is, without having gaps in your code or awkwardly saving current output PC in some variable to reuse it for some other "* =" further down or similar.
2020-06-30 10:45
JackAsser

Registered: Jun 2002
Posts: 1680
Quote: The point is that the current program counter is just one of many attributes of a program section/segment. Once you commit to using them, you have better and more elegant control. Then you also prefer to manipulate section attributes rather than rely on the old blunt tool that is "* =".

And besides, can you easily continue right where some other part of code ended, just by using "* ="? That is, without having gaps in your code or awkwardly saving current output PC in some variable to reuse it for some other "* =" further down or similar.


@Oswald: Trust me and Krill on this. Only having *= for Eye of the Beholder would have been a disaster. PC and relative PC are just some of many attributes for a segment.

@Sasq: I suggest you take a look at LD65 and how they separate memory and segments as two different entities. It's quite elegant and you should be able to copy those concepts and instead of a separate link file you can have it directly in the source. https://www.cc65.org/doc/ld65-5.html
2020-06-30 11:07
Sasq

Registered: Apr 2004
Posts: 106
The question is still do we need "nested" sections.

So how would this work with a separate segment for ram_fn ?

!section "bank5", $058000

  jsr copy_fn
  jsr $c000
  rts  

copy_fn:
  stx ram_fn_end-ram
$ lda ram_fn,x
  sta $c000,x
  dey
  bne -
  rts
  
  !pc $c000
ram_fn:
  nop
  rts


I guess you need something like

!section "ram_fn", start=sections.bank5.end, pc=$c000
ram_fn:
  nop
  rts


Except hardcoding start is inflexible, ideally you want to
tell the assembler to place section anywhere withing a certain area... hence the division between memory and section in LD65...

Ok so I'll introduce memory areas, and then you can specify section start to either a specific address, or a memory area.

So we should not need something weird like wrapping the ram_fn in a nested section hopefully.
2020-06-30 11:45
Krill

Registered: Apr 2002
Posts: 1475
I recently needed* nested sections.

This was for a portion of code that is copied from somewhere to RAM under $d000 after run, modified in that IORAM section, then later on transferred to the drive and executed there somewhere below $0800.

The nesting came in handy for sharing that IORAM section between drive code and other stuff not executed on the drive.

* Could have done without, mind, but a lot less elegantly and with some more potential sources of bugs.
2020-06-30 16:49
oziphantom

Registered: Oct 2014
Posts: 404
a case from 64Tass which has an internal linker, which lets you do crazy stuff.

So you have an IRQ handler, but you have 2, 1 PAL and 1 NTSC and you want to copy it to RAM but you want a hole big enough for it to be copied.
Then you want the some parts of the IRQ handler to be in the same address so other code can reference them.

so you have
* = Location in ROM File
IRQ_NTSC_START
.dsection sIRQ_NTSC
IRQ_PAL_START
.dsection sIRQ_PAL

.logical IRQ_DEST ; make the code assemble as if its in RAM
.section IRQ_NTSC
.section IRQ_NTSC_ENTER
.block IRQ_NTSC
IRQ_ENTER 
...code..
.ends 
.align size(IRQ_NTSC_ENTER) >? size(IRQ_PAL_ENTER) ; make sure first is in the same sport
IRQ_FIRST
...code...

IRQ_SECOND
...code...

IRQ_THRID
...code...

.bend ; NTSC IRQ
.ends; NTSC IRQ Handler
.here

.logical IRQ_DEST
.section sIRQ_PAL
.section IRQ_PAL_ENTER
.block IRQ_PAL
IRQ_ENTER 
...code..
.ends 
.align size(IRQ_NTSC_ENTER) >? size(IRQ_PAL_ENTER) ; make sure first is in the same sport
IRQ_FIRST
...code...

IRQ_SECOND
...code...

IRQ_THRID
...code...

.bend
.ends; PAL IRQ Handler
.here 

then in the main code you have

IRQ_DEST
.fill size(sIRQ_NTSC) ?> size(sIRQ_PAL)
IRQ_FIRST = IRQ_PAL.IRQ_FIRST
cerror IRQ_NTSC.IRQ_FIRST != IRQ_PAL.IRQ_FIRST, "align filed" 


(all of the top of my head so the .section, .block and .logical order might be wrong
2020-06-30 18:31
Count Zero

Registered: Jan 2003
Posts: 1107
Just like Jackasser and Frantic already mentioned some cartridge related stuff, this is how I tried to do it in Dreamass - unfortunately after the macro call the PC is off by one ("segmentof" still needs to be fixed on Dreamass) :(

However most inportant for us when asking DocBacardi for features was allowing setting up cart banking like:

                        #segdef "bank0",$8000-$A000, fillup, force, $bb, abs
                        #segdef "bank1",$8000-$A000, fillup, force, $bb, abs

                        #outfile @, "bank0", "bank1"

                        #include "macros.src"

                        #include "bank0.src"
                        #include "bank1.src"


That way problems on missing labels when referencing them in another bank are circumvented as Dreamass has access to all labels and something like ".Bankjsr (somerout)" can be handled by a macro with

#if segmentof {subroutine} != BANKNAME 

with BANKNAME being (re)-defined in bank0, bank1, etc. to allow comparison in the macro.

Of course the project wont exceed 64kb here so we didnt see a reason for 24bit addresses.

There is little more to it. Looking at the bass tutorials and stuff something similar should be possible for smaller cart projects, hm?

Some current bass features look nice while of course quite a few things are not my cup of tea :)
2020-06-30 23:15
Oswald

Registered: Apr 2002
Posts: 4584
Quote: @Oswald: Trust me and Krill on this. Only having *= for Eye of the Beholder would have been a disaster. PC and relative PC are just some of many attributes for a segment.

@Sasq: I suggest you take a look at LD65 and how they separate memory and segments as two different entities. It's quite elegant and you should be able to copy those concepts and instead of a separate link file you can have it directly in the source. https://www.cc65.org/doc/ld65-5.html


I trust both of you, I just think assembler functionality like this is often used unecessarily. Segments are not needed to change location of stuff in memory as it was explained here.

Oziphantom's example could be a simple .if PAL then PALIRQ .else NTSCIRQ fex. and the routine needed to be referenced by other code could just use a label.

I would like an assembler that makes code easyer to read and write.

fex in the BadAss example:

!rept 256 { !byte (sin(i*Math.Pi*2/256)+1) * 100 + 24 }

we use sines so often, why cant it be just like FullSine(Length,Max,Min)

(ok can be done through imported functions, that looks really nice in BadAss, but after 30 years of using ".", I cant stomach "!" :)
2020-07-01 00:13
JackAsser

Registered: Jun 2002
Posts: 1680
Quote: I trust both of you, I just think assembler functionality like this is often used unecessarily. Segments are not needed to change location of stuff in memory as it was explained here.

Oziphantom's example could be a simple .if PAL then PALIRQ .else NTSCIRQ fex. and the routine needed to be referenced by other code could just use a label.

I would like an assembler that makes code easyer to read and write.

fex in the BadAss example:

!rept 256 { !byte (sin(i*Math.Pi*2/256)+1) * 100 + 24 }

we use sines so often, why cant it be just like FullSine(Length,Max,Min)

(ok can be done through imported functions, that looks really nice in BadAss, but after 30 years of using ".", I cant stomach "!" :)


I kinda agree with you. :) Maybe both could be supported. *= for the quick hacks and segments for full blown cart dev. Also agree on . vs ! :D
2020-07-01 00:23
Krill

Registered: Apr 2002
Posts: 1475
Agree with . rather than !, rest not sure. :)
2020-07-01 01:14
Sasq

Registered: Apr 2004
Posts: 106
I really wanted dots for local labels, as it naturally appends to the last non local label;
copy:
   nop
.loop
   dex
   beq .loop

Here “.loop” just becomes “copy.loop”
2020-07-01 01:36
Frantic

Registered: Mar 2003
Posts: 1432
@sasq: I'm with you there. Also, I've been using ACME for a whole bunch of years, so the ! notation comes quite naturally by now. :)

Speaking of dots at the start of local labels: It is nice if the assembler can spit out all the labels to a file which is compatible with the VICE command line parameter "-moncommands", e.g. something that looks like:

al C:1004 .PL_SP1_chn01
al C:1022 .PL_SP2_chn01
al C:103f .PL_SETPARAMFLAG_chn01
al C:1043 .PL_PARAM_chn01
al C:1048 .PL_SETNOTEFLAG_chn01
al C:104c .PL_NOTE_chn01
al C:1057 .PL_SP1_chn02
al C:1075 .PL_SP2_chn02
al C:1092 .PL_SETPARAMFLAG_chn02
al C:1096 .PL_PARAM_chn02
al C:109b .PL_SETNOTEFLAG_chn02
al C:109f .PL_NOTE_chn02
al C:10aa .PL_SP1_chn03
al C:10c8 .PL_SP2_chn03
al C:10e5 .PL_SETPARAMFLAG_chn03
al C:10e9 .PL_PARAM_chn03
al C:10ee .PL_SETNOTEFLAG_chn03


Note that all labels have a dot at their beginning here, even if those are not local labels in the original ACME source code.
2020-07-01 09:15
oziphantom

Registered: Oct 2014
Posts: 404
Quoting Oswald
Oziphantom's example could be a simple .if PAL then PALIRQ .else NTSCIRQ fex. and the routine needed to be referenced by other code could just use a label.


Please tell me how you can use an if/else to handle the case of having PAL And NTSC stored in ROM in a cart that copies the right version into RAM as the game boots depending upon which hardware it is plugged in to. And how you would have just a label to handle reference by other code.
2020-07-01 09:51
Oswald

Registered: Apr 2002
Posts: 4584
Ozi, my bad I made wrong assumptions what you are doing there. anyway 6 "." directives seems a lot for some irq assembly...

Sasq, why "." cant e used for directives and label hierarhy too? an algorithm can differentiate if its a . infront of a keyword or after a label?
2020-07-01 10:24
Groepaz

Registered: Dec 2001
Posts: 9317
one reason: to do that, you must know all and every keyword that you will ever use in advance, our your sources will randomly break in the future. it also makes the parser much easier and less messy to do. and its more consistent too.
2020-07-01 13:44
Sasq

Registered: Apr 2004
Posts: 106
I can add a '--dot-meta' option that would

* Change prefix of meta to dot
* Require that you not put any meta commands or opcodes in the first column
* Require that you _do_ put assignments in the first column

.local_symbol = 3
    .print .local_symbol
    lda #.local_symbol
    beq .skip
.skip
    rts


... but I don't really like it :)
2020-07-01 19:12
Sasq

Registered: Apr 2004
Posts: 106
This is how it's starting to work now. Needs tweaking for sure but will give a lot of possibilities.

!section "ZP", start=$00, size=$100, flags=NoStore
!section "RAM", start=$801, size=$9f00-$0801, flags=NoStore
;!section "HIRAM", start=$a000, size=$2000, NoStore
!memory "HIRAM",$a000,$2000

!section "DATA", in="RAM", flags=NoStore


!section "main", in="RAM", flags=First {
    !section "ZP" {
        var0: !ds 1
    }
start:
    sei
    !section "sine" in="DATA" {
        sine: !rept 256 { !byte sin(i) }
    }
    lda sine,x
    sta var0
}

; Put pointer to given string or array in XY
!macro xyptr(a) {
    !section "DATA" {
.local
        !fill a
    }
    ldx #>.local
    ldy #<.local
}

!section "extra", in="HIRAM" {

}

!section "other", in="HIRAM" {

}



Sections

!section <args...> [ { <statements> } ]


Arguments can be positional or named. The arguments are in order:

name - Name of the section to open up or create
start - Start address of the section (load address)
pc - Initial Program counter for this section (runtime address)
flags - Flags for the section
in - Parent section for this section
size - Fixed size of this section
fill - Fill char for this section if not filled up to _size_

If _name_ is not provided, an anonymous section is created.

If _start_ is provided, this creates a new section. It is an error
if a section with this name already exists.

If _start_ is not provided, _name_ must exist or this must be a child
section.

if _pc_ is not provided, it defaults to _start_.

Flags
NoStore: means this section will not be saved.
ReadOnly: means it will be located in ROM
First: means this section should come first in its parent


if _in_ is specified, this section is a child section.

A child section can not be reopened, and does not need to be named.

A child section will start at it's parents start, and will increase
it's parent pc to it's size.

A parent section should not have a different load and runtime address

The parent of a child section _must_ be a NoStore section.

Opening up an existing section and creating a child section is similar,
except in the latter case a new section is created.




`!memory <name> <start> <size>`

Short hand to create a NoStore section that can be the parent of other sections
2020-07-01 19:38
JackAsser

Registered: Jun 2002
Posts: 1680
Yeah, that feels like a nice approach. With that you could also include the section definitions externally and thus have a structure similar to ca65's link-files.
2020-07-02 13:56
Sasq

Registered: Apr 2004
Posts: 106
Ok now this:

Sections form a tree. Only leaf sections may contain data.

You can not "open up" sections, only add a section to a
parent section.

Root sections usually have fixed size and fixed start.

After an assembly pass, go through the tree and place all sections sequentially in their parent.
Now all sections will have a fixed start address.

If any section was moved, we need to do another pass.

; Root sections
!section "RAM" start=$0000 size=64*1024 NoStore
!section "ZP" start=$00 size=256 NoStore

; Non-leaf section
!section "text" in="RAM" NoStore Last

; Leaf section
!section "code" in="RAM", start=$801 {
    ; Basic start and such
    ; Another leaf section, defined recursively
    !section in="text" {
        name: !text "name"
    }
    lda name,x
}

2020-07-02 14:41
JackAsser

Registered: Jun 2002
Posts: 1680
What does NoStore mean in a parent section actually?
2020-07-02 14:57
Sasq

Registered: Apr 2004
Posts: 106
Well NoStore should be implied in any non-leaf section now.

It means it will not be any data in the section.
2020-07-03 08:53
JackAsser

Registered: Jun 2002
Posts: 1680
Quote: Well NoStore should be implied in any non-leaf section now.

It means it will not be any data in the section.


Yup, I guessed as much. You really need output directives to root sections also, i.e. to what file they should be emitted.
2020-07-03 11:03
Sasq

Registered: Apr 2004
Posts: 106
Sure, that already works. Although I need to allow file ouput section to overlap I guess.
2020-07-03 12:10
Sasq

Registered: Apr 2004
Posts: 106
Here is the new Section documentation (and other meta commands):

https://github.com/sasq64/bass/blob/new-sections/docs/META.md
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
Durandal
josepzin/Nautilus
Style/Chrome
Guests online: 28
Top Demos
1 Coma Light 13  (9.7)
2 Uncensored  (9.7)
3 Edge of Disgrace  (9.7)
4 Comaland 100%  (9.6)
5 Unboxed  (9.6)
6 The Shores of Reflec..  (9.6)
7 Lunatico  (9.5)
8 Remains  (9.5)
9 NGC 1277 100%  (9.5)
10 Wonderland XII  (9.4)
Top onefile Demos
1 Dawnfall V1.1  (9.6)
2 Listen to Your Eyes  (9.6)
3 MD202006 - Get Well ..  (9.6)
4 The Tuneful Eight [u..  (9.5)
5 Smile to the Sky  (9.5)
6 Crystal Gazer  (9.5)
7 Instinct  (9.5)
8 Coro(l)na Nuthouse  (9.5)
9 Rewind  (9.5)
10 Bad Boy  (9.5)
Top Groups
1 PriorArt  (9.6)
2 Performers  (9.5)
3 Booze Design  (9.4)
4 Fossil  (9.4)
5 Censor Design  (9.4)
Top Musicians
1 Rob Hubbard  (9.7)
2 LMan  (9.7)
3 Jeroen Tel  (9.6)
4 Linus  (9.6)
5 Drax  (9.5)

Home - Disclaimer
Copyright © No Name 2001-2020
Page generated in: 0.129 sec.