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


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

Registered: Apr 2004
Posts: 155
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: 1627
Looks quite nice at first glance!
2020-06-28 19:58
chatGPZ

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

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

/Bacchus
2020-06-28 21:04
Sasq

Registered: Apr 2004
Posts: 155
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: 1989
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: 155
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: 2839
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: 1989
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: 2839
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: 2839
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: 155
@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: 2839
Awesome! \=D/
2020-06-28 21:32
Sasq

Registered: Apr 2004
Posts: 155
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: 1989
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: 1989
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: 155
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: 2839
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: 1989
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: 2839
Would a .sectionof(label) directive allow for that? Sections are named, of course.
2020-06-28 21:53
JackAsser

Registered: Jun 2002
Posts: 1989
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: 155
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: 1989
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: 155
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: 1627
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: 2839
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: 1627
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: 155
@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: 1627
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
Account closed

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

Registered: Jun 2002
Posts: 1989
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: 2839
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: 1627
Yes, that's what I tried to say. What Jackasser said, basically.
2020-06-29 13:57
Sasq

Registered: Apr 2004
Posts: 155
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: 1627
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
Account closed

Registered: Jan 2018
Posts: 212
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: 155
@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: 155
@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
Account closed

Registered: Jan 2018
Posts: 212
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: 155
@Golara: I think both those links are for the windows build...
2020-06-29 17:06
Frantic

Registered: Mar 2003
Posts: 1627
@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
Account closed

Registered: Jan 2018
Posts: 212
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: 5017
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: 1989
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: 5017
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: 2839
Just like chisel and hammer also work to write your next novel, yes.
2020-06-30 05:56
Oswald

Registered: Apr 2002
Posts: 5017
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: 2839
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: 1989
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: 155
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: 2839
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: 478
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: 1821
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: 5017
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: 1989
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: 2839
Agree with . rather than !, rest not sure. :)
2020-07-01 01:14
Sasq

Registered: Apr 2004
Posts: 155
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: 1627
@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: 478
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: 5017
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
chatGPZ

Registered: Dec 2001
Posts: 11108
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: 155
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: 155
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: 1989
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: 155
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: 1989
What does NoStore mean in a parent section actually?
2020-07-02 14:57
Sasq

Registered: Apr 2004
Posts: 155
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: 1989
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: 155
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: 155
Here is the new Section documentation (and other meta commands):

https://github.com/sasq64/bass/blob/new-sections/docs/META.md
2020-07-23 22:59
Sasq

Registered: Apr 2004
Posts: 155
Beta4 update. Changes include:

* Indexed labels, for accessing labels inside macros and rept statements
* New section system, child sections etc
* Unicode strings
* !check for runtime asserts in 6502 code
* Better error reporting

https://github.com/sasq64/bass/releases
2020-07-23 23:45
Frantic

Registered: Mar 2003
Posts: 1627
Good work there, sir! I didn't manage to build bass on my MacOS 10.13 system though, due to various errors when compiling. Too bad.
2020-07-24 08:53
Sasq

Registered: Apr 2004
Posts: 155
Yes Apples clang still lacks many C++17 features. I'll see what I can do...
2020-07-24 09:42
Boogaloo

Registered: Aug 2019
Posts: 21
I'm following this with great interest. I'll try it out soonish. Great work so far!

(And I agree with JackAsser about the clean C++ code.)
2020-07-24 10:04
Sasq

Registered: Apr 2004
Posts: 155
OK, removed shared_ptr<T[]> which is not supported by OSX yet it seems, should build now.
2020-07-24 10:10
Sasq

Registered: Apr 2004
Posts: 155
@Boogaloo Thanks!
2020-07-24 10:12
Sasq

Registered: Apr 2004
Posts: 155
Here is an example of indexed labels and unit testing, based
on a snippet from Trash that wanted this feature;

; constant D011VALUE == value in d011

D011VALUE = 0

!macro DrawRasterColors(row) {
    !if (row & 7) == (D011VALUE & 7) {
    ; 23 cycle macro
    col[row]:
        lda #0                  ;  2
        sta $d020               ;  6
        sta $d021               ; 10
        !rept 5 { nop }
        bit $ea                 ; 23
    } else {
    ;63 cycle macro
    col[row]:
        lda #0                  ;  2
        sta $d020               ;  6
        sta $d021               ; 10
        !rept 25 { nop }
        bit $ea                 ; 63
    }
}

!section "main", $c000

!rept 6*8 {
    DrawRasterColors(i + $40)
}

!test "bad" {
    DrawRasterColors(0)
}
!assert tests.bad.cycles == 23

!test "good" {
    DrawRasterColors(1)
}
!assert tests.good.cycles == 63

!test "modify" {
    lda #9
    sta col[$40]+1
    lda #8
    sta col[$41]+1
}
!assert tests.modify.ram[$c001] == 9
!assert tests.modify.ram[$c010] == 8
2020-07-25 08:41
Oswald

Registered: Apr 2002
Posts: 5017
indexed labels is nice, lot of guys need that when creating selfmodded speedcode with macros :)
2020-09-16 10:34
Raistlin

Registered: Mar 2007
Posts: 552
I was interested in trying out this assembler .. but .. trying to compile the source, I'm getting some problems..

On Windows, CMake is refusing to generate the compile_commands.json file ....

Anyone know what might be needed to get this compiling on Windows?
2020-09-17 21:12
Sasq

Registered: Apr 2004
Posts: 155
`compile_commands.json` are not needed for building, only for Intellisense features in editors such as Visual Studio Code.
2020-09-17 21:30
Sasq

Registered: Apr 2004
Posts: 155
The `dev` branch is where it's happening BTW.

The following is an example on how you can let the assembler "pre-render" sid register data for faster playback (like the Dane part in Edge of Disgrace):

    !script "../lua/sid.lua"

    data = load("../data/test.sid")
    sid = sid_parse(data)
    
    !section "music", sid.load
music:
    !fill sid.data

%{

    sid_data = nil

    function generate_data()

        map_bank_write(0xd4, 1, function(adr, val)
            if sid_data then
                table.insert(sid_data, adr - 0xd400)
                table.insert(sid_data, val)
            end
        end)

        start_run()
        init = sym("sid.init")
        play = sym("sid.play")
        set_a(0)
        call(init)
        sid_data[#sid_data - 1] = sid_data[#sid_data - 1] | 0x80
        for i=1,15*50 do
            l = #sid_data
            call(play)
            if l ~= #sid_data then
                sid_data[#sid_data - 1] = sid_data[#sid_data - 1] | 0x80
            else
                print("Silent frame")
            end
        end
    end

    function get_sid_data()
        sid_data = {}
        generate_data()
        result = sid_data
        sid_data = nil
        return result
    end
}%

    !text "SID"
sid_data:
    !fill get_sid_data()
2020-09-17 22:28
JackAsser

Registered: Jun 2002
Posts: 1989
Quote: The `dev` branch is where it's happening BTW.

The following is an example on how you can let the assembler "pre-render" sid register data for faster playback (like the Dane part in Edge of Disgrace):

    !script "../lua/sid.lua"

    data = load("../data/test.sid")
    sid = sid_parse(data)
    
    !section "music", sid.load
music:
    !fill sid.data

%{

    sid_data = nil

    function generate_data()

        map_bank_write(0xd4, 1, function(adr, val)
            if sid_data then
                table.insert(sid_data, adr - 0xd400)
                table.insert(sid_data, val)
            end
        end)

        start_run()
        init = sym("sid.init")
        play = sym("sid.play")
        set_a(0)
        call(init)
        sid_data[#sid_data - 1] = sid_data[#sid_data - 1] | 0x80
        for i=1,15*50 do
            l = #sid_data
            call(play)
            if l ~= #sid_data then
                sid_data[#sid_data - 1] = sid_data[#sid_data - 1] | 0x80
            else
                print("Silent frame")
            end
        end
    end

    function get_sid_data()
        sid_data = {}
        generate_data()
        result = sid_data
        sid_data = nil
        return result
    end
}%

    !text "SID"
sid_data:
    !fill get_sid_data()


Hehe, awesome!
2020-09-17 22:36
Mr. SID

Registered: Jan 2003
Posts: 421
Yeah, you can do stuff like that with k2asm and Python too. Some of it is useful and other things are masturbatory coding... :)
2020-09-17 22:40
Sasq

Registered: Apr 2004
Posts: 155
Does k2asm also contain an emulator?
Otherwise I can't see how it can do this.
2020-09-17 23:49
Mr. SID

Registered: Jan 2003
Posts: 421
No, but you can do pretty much anything in Python these days: https://github.com/docmarionum1/py65emu
2020-09-18 22:38
Compyx

Registered: Jan 2005
Posts: 631
Hot damn, there's PLA in play*. An actual mnemonic in a shitload of 'code'.
2020-12-11 16:16
Sasq

Registered: Apr 2004
Posts: 155
I have done several improvements now, including a built in "fantasy" text mode 6502 system.

This allows you to prototype program to run directly in the terminal.

Made a short & ugly screencast about it:

https://youtu.be/g1uuhz7Qupw

Manual is also coming along, and the "hardware" of the text mode system is documented at the end:

http://apone.org/bass/
2021-04-13 13:17
Krill

Registered: Apr 2002
Posts: 2839
Just came across something which might or might not be a sensible and valuable feature for a 6502 assembler:

Interleaving code.

Sometimes, you really want to mix two "unrelated" sources at build time, with various constraints.

E.g., intermingling multispeed/sample-replay with VIC raster stuff and other (branch-less unrolled) code as to minimise context-switching overhead.

Or, putting little NMI handlers into pages which also happen to hold some other (fully branching) code.

The question would be, should an assembler handle that (instead of some higher-level compiler-like thing), and how to formalise/formulate the constraints.
2021-04-13 13:18
chatGPZ

Registered: Dec 2001
Posts: 11108
support for interleave code with fpp data? yes please :)
2021-04-13 13:23
Krill

Registered: Apr 2002
Posts: 2839
Quoting Groepaz
support for interleave code with fpp data? yes please :)
Indeed, mixing executable code with other data is also something you need here and there. :)
2021-04-13 14:35
map

Registered: Feb 2002
Posts: 27
'Some higher-level compiler-like thing' for this problem seems to be invented it seems.
At least according to Raistlins comment here:
https://csdb.dk/release/?id=195841&show=notes#notes

Quoting name
**Raistlin’s Code Generator**
Note that most of Raistlin’s parts used his C++ tool for generating highly optimised/unrolled ASM. It’s able to neatly interleave any “grunt” code (such as bitmap/char/sprite plotting) into accurately timed IRQ code (eg. For border opening). With this, opening borders and such is very simple - allowing the coder to concentrate on optimising the plotting algorithms. Without the tool, we shudder to think how someone might go about achieving some of the things we made for this demo ;-)


Actually I'm wondering if Raistlin would like to share that tool, or at least some more details. :-)
2021-04-13 14:39
JackAsser

Registered: Jun 2002
Posts: 1989
See S:T Lars Meeting III - Invite source
2021-04-13 14:42
Krill

Registered: Apr 2002
Posts: 2839
Quoting map
'Some higher-level compiler-like thing' for this problem seems to be invented it seems.
Why yes, that kind of stuff is something like a d64 image tool, in that every coder sooner or later rolls their own custom implementation (and repeats all the mistakes done by others before). :)

But an open and generic tool for that would be nice, and possibly included with an actual assembler.
2021-04-13 14:50
chatGPZ

Registered: Dec 2001
Posts: 11108
yes - and to be useful for the generic case it really needs support by the assembler. and its a quite tricky problem to solve too, similar to jackassers recent pack-code-into-banks challenge :)
2021-04-13 15:25
JackAsser

Registered: Jun 2002
Posts: 1989
Quote: See S:T Lars Meeting III - Invite source

This one tracks register usage and cycles in the speed code in one code base and nops in another timed codebase and merges them while maintaining critical timing.
2021-04-13 15:26
JackAsser

Registered: Jun 2002
Posts: 1989
Quote: yes - and to be useful for the generic case it really needs support by the assembler. and its a quite tricky problem to solve too, similar to jackassers recent pack-code-into-banks challenge :)

Which worked extremely well. I now have a prelinker scripts that digests all .o and .lib files and actually generates the link file for ld65. A prelinker. Freed up alot of space.
2021-04-13 15:37
Krill

Registered: Apr 2002
Posts: 2839
Quoting JackAsser
This one tracks register usage and cycles in the speed code in one code base and nops in another timed codebase and merges them while maintaining critical timing.
Yes, and that kind of stuff would have to be formalised for a generic tool. =)
2021-04-13 15:37
Rex

Registered: Sep 2011
Posts: 14
For borderline pacman I coded a cycle-based code merger in C for merging cycle-exact raster code (opening the side-borders, displaying 9 sprites per rasterline etc.) with BOB-rendering code (rendering pacman and ghosts plus updating changed tiles).

In my case the raster-code has defined "cycle holes" with number of cycles that has to be spent and the BOB-code is split into tiny "atomic" blocks marked with the number of cycles the block uses. The code merger is short and runs on the c64 itself - it fills up the "cycle holes" with BOB-codes and NOP/BIT$EA to ensure the exact number of cycles is produced.

https://gitlab.com/camelot/kickc/-/blob/master/src/test/kc/comp..

This was the specific type of merging I needed for that effect. Other effects will need other types of code merging. Merging code and data will require another completely different merging strategy.

I am not sure that a general solution for the "merging problem" does exist. It would be interesting to see some ideas on what a general solution could look like.
2021-04-13 15:46
Krill

Registered: Apr 2002
Posts: 2839
Quoting Rex
It would be interesting to see some ideas on what a general solution could look like.
I propose... a combined superset of various use-cases and their individual strategies. =)

But i guess the "FPP data"/"NMI handlers" problem would be the easiest to solve first. As in, have some fixed gaps in the code to assemble around.
2021-04-13 15:57
Raistlin

Registered: Mar 2007
Posts: 552
Nice work, Rex - I use something similar in my all-border DYPPs and other such effects ... though I generate everything on PC by having CPP spit out ASM files.

There are some interesting optimizations to be had with this sort of stuff .. for example, where you have a 13 cycle gap and the code you want to insert is just STAs (4 cycles each). Use 12 cycles and you're left with a 1-cycle "problem... so you use 8 cycles instead, "wasting" 4-5. In my code, where possible, I made it such that I could easily waste an additional cycle - so using STA ----, Y for example, ensuring that the indexed write will always cross a page boundary (and therefore eat an extra cycle). Not always possible of course... but well worth it when it is.
2021-04-13 16:06
Krill

Registered: Apr 2002
Posts: 2839
Quoting Raistlin
STA ----, Y for example, ensuring that the indexed write will always cross a page boundary (and therefore eat an extra cycle).
So... formalise as "sta label,_y"? (without index or with y.) :)

(And i believe STA mem16,Y has a cycle count independent of page crossings: always 5.)
2021-04-13 16:19
Raistlin

Registered: Mar 2007
Posts: 552
Sorry, I’m mixing my STA and LDA timings :-)
2021-04-13 16:26
Krill

Registered: Apr 2002
Posts: 2839
Ok, well, thinking a bit further about it, this is one of the few things where a Turing-complete scripting language native to the assembler would come in handy. (Not much of a fan of that otherwise, one hammer vs. world made of nails and so.)

Something where stateful user code can do accounting and control emission of opcodes, etc.
2021-04-13 17:06
Rex

Registered: Sep 2011
Posts: 14
That is a neat optimization Raistlin!

Another option would be marking some of the logic code blocks as independent to allow the merger to re-organize them to fill the available cycles with as much active code as possible.

One general need is probably the cycle-exact code merging. A solution for that should be able to fill cycle gaps in cycle-exact raster code. This requires the ability to keep track of cycle counts. A general solution should probably also support keeping track of (and handling) register usage. Smart optimizations like what you are proposing would also be nice.

Merging code and data in memory under constraints is probably a different use-case with different requirements.
2021-04-13 17:14
chatGPZ

Registered: Dec 2001
Posts: 11108
rearranging code in cycle exact code doesnt only require tracking cycle count... you also have to track where in the line you are and consider the dma setup cycles. sounds like fun =)
2021-04-13 17:57
Raistlin

Registered: Mar 2007
Posts: 552
Just to throw another spanner into this already quite complex system...

Something else that I do on C++ side is that I have some "loose" setup things that need to be done .. so, for example, it's common to want to move the Sprite Y values down every 21 lines. Except of course it doesn't need to be on exact lines - it can be almost anywhere within the existing line of sprites - so you have ~20 raster lines where it could happen for every 21.

I effectively make that a low-importance task - but higher importance than the "slow" task (which is usually something like the blitting of the DYPP or circle scroll).

And... it's good to know what raster-line you're on at each point - when scrolling D800 data, or when updating bitmap data etc, it's good to know whether you're behind or ahead of the raster.

Coding all of this, and keeping within memory budgets, is quite a task ;-)
2021-04-14 00:50
Krill

Registered: Apr 2002
Posts: 2839
Quoting Raistlin
Coding all of this, and keeping within memory budgets, is quite a task ;-)
Top Coders
	
1 Raistlin  (9.8)
2 Graham  (9.8)
3 Crossbow  (9.8)
That top spot don't come from nothin'. =)
2021-04-14 03:49
map

Registered: Feb 2002
Posts: 27
Quoting Krill

But an open and generic tool for that would be nice, and possibly included with an actual assembler.


I totally agree that it would be nice to have such a tool. Maybe even nicer to have the possibility to combine it with the assembler of your choice instead of having it build into a certain assembler only.
2021-04-14 21:37
Jammer

Registered: Nov 2002
Posts: 1289
Looks great from the first look! <3
2021-04-14 23:12
Krill

Registered: Apr 2002
Posts: 2839
Quoting map
I totally agree that it would be nice to have such a tool. Maybe even nicer to have the possibility to combine it with the assembler of your choice instead of having it build into a certain assembler only.
That's a good point.

Another would be that it can take quite long to generate good solutions to the problem (which is quite often NP-complete or worse), and you'd want to keep intermediate artefacts for speedier rebuilds and retain some manual control over the process. Pretty similar to synthesised netlists in FPGA/PLD stuff.
2021-04-15 15:24
Sasq

Registered: Apr 2004
Posts: 155
So if you had something like this, how far would that get you? :

!delay <cycles>, <regs_to_preserve>

!merge <section1>, <secition2>, <max_cycles>


Where merge was allowed to insert any code in the delay "slots"
as long as registers where preserved ?
2021-04-15 22:24
Zaz

Registered: Mar 2004
Posts: 33
Quoting Krill
Quoting Raistlin
Coding all of this, and keeping within memory budgets, is quite a task ;-)
Top Coders
	
1 Raistlin  (9.8)
2 Graham  (9.8)
3 Crossbow  (9.8)
That top spot don't come from nothin'. =)


Well, I did most of the things mentioned and some others 8 years ago, such as https://csdb.dk/release/?id=121570, so the coder rating can't be just from mastering cycle exact code generation ;-)

To be more on topic, I don't think this kind of feature is something for the assembler, the problem is of a different kind. The code generation for this needs to know where all the multiplexed sprites are, as well as the bad lines...
2021-04-16 00:13
JackAsser

Registered: Jun 2002
Posts: 1989
Quote: Quoting Krill
Quoting Raistlin
Coding all of this, and keeping within memory budgets, is quite a task ;-)
Top Coders
	
1 Raistlin  (9.8)
2 Graham  (9.8)
3 Crossbow  (9.8)
That top spot don't come from nothin'. =)


Well, I did most of the things mentioned and some others 8 years ago, such as https://csdb.dk/release/?id=121570, so the coder rating can't be just from mastering cycle exact code generation ;-)

To be more on topic, I don't think this kind of feature is something for the assembler, the problem is of a different kind. The code generation for this needs to know where all the multiplexed sprites are, as well as the bad lines...


"Well, I did most of the things mentioned and some others 8 years ago, such as https://csdb.dk/release/?id=121570, so the coder rating can't be just from mastering cycle exact code generation ;-)"

It's defined by "food, right now". ;)

@Raistilin: Love u, so no offence! <3
2021-04-16 00:15
JackAsser

Registered: Jun 2002
Posts: 1989
Quote: So if you had something like this, how far would that get you? :

!delay <cycles>, <regs_to_preserve>

!merge <section1>, <secition2>, <max_cycles>


Where merge was allowed to insert any code in the delay "slots"
as long as registers where preserved ?


Regs to preserve might be a nice annotation. In my merger I tracked LDA-ish instructions to know if a reg became dirty.

Also elaborate on merge!

Typically you have one code chunk with speed code and another one with raster code with timing critical parts. The speed code should be interleaved with the raster code and maintain 1) raster code timing and 2) register usage on speed code. To ease up constraints one might ignore a) branch penalties 2) char fetch DMA and 3) sprite DMA
2021-04-16 15:12
Raistlin

Registered: Mar 2007
Posts: 552
This does seem like something that’s not really for the compiler ... a separate tool that spits out ASM files might work. I have that now in a sense - but it’s not a generic solution, I have some C++ helper libraries and then I’ll typically have one C++ file per demo effect that I create using this - that C++ creating all my needed data files, pre-visualisations of the effect, etc etc. Those C++ files can run pretty huge ... my C++ skills aren’t the best - but, well, they’re just for me - and it’s the resultant ASM that matters ;-)

As said, though, I don’t think it’s particularly the merging of code that people might need help with ... it’s also what that 2 branches of code is in the first place - and how to try to reduce register usage in a way that 2 different sets of code can run without lots of register saving and reloading. How will a generalised merge tool work well with that I wonder?
2021-04-16 15:15
Raistlin

Registered: Mar 2007
Posts: 552
“ the coder rating can't be just from mastering cycle exact code generation ;-)”

The charts on CSDb don’t make a whole lot of sense - and particularly break down when there are lower vote counts. Feel free to downvote me and mould the chart how you think it should be. I don’t take much notice nor care to it tbh. No Crest demos in the top 10, for instance, is a crime against humanity... me being placed higher than HCL and Axis is also utter madness - but unsustainable (wait till there are 20 votes cast).
2021-04-16 15:49
Jammer

Registered: Nov 2002
Posts: 1289
LOL, I'm in coders' TOP5?! WTF?! I can't even cycle :D
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
Mason/Unicess
krissz
MCM/ONSLAUGHT
zscs
psych
Guests online: 150
Top Demos
1 Next Level  (9.8)
2 Mojo  (9.7)
3 Coma Light 13  (9.7)
4 Edge of Disgrace  (9.6)
5 Comaland 100%  (9.6)
6 No Bounds  (9.6)
7 Uncensored  (9.6)
8 The Ghost  (9.6)
9 Wonderland XIV  (9.6)
10 Bromance  (9.6)
Top onefile Demos
1 It's More Fun to Com..  (9.8)
2 Party Elk 2  (9.7)
3 Cubic Dream  (9.6)
4 Copper Booze  (9.5)
5 Rainbow Connection  (9.5)
6 TRSAC, Gabber & Pebe..  (9.5)
7 Onscreen 5k  (9.5)
8 Wafer Demo  (9.5)
9 Dawnfall V1.1  (9.5)
10 Quadrants  (9.5)
Top Groups
1 Oxyron  (9.3)
2 Nostalgia  (9.3)
3 Booze Design  (9.3)
4 Censor Design  (9.3)
5 Crest  (9.3)
Top Logo Graphicians
1 Sander  (10)
2 Facet  (9.7)
3 Mermaid  (9.4)
4 Pal  (9.4)
5 Shine  (9.3)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.606 sec.