fadden / 6502bench

A workbench for developing 6502 code
https://6502bench.com
Apache License 2.0
166 stars 33 forks source link

Provide way to isolate regions #139

Closed BacchusFLT closed 3 months ago

BacchusFLT commented 1 year ago

The region function works really well, but once defined and you realise that you need to change the end of it, you can't. Is there any reason it's not possible to update the selected range here? I tend to do a preliminary selection, but the program requires that you make a final selection once you define it.

fadden commented 1 year ago

In the docs, under Editors > Create/Edit Address Region:

Resize If you select multiple lines, and the first line is an address region start directive, you will be able to resize that region to the selection. By definition, the updated region will have a fixed end point.

So just select the new region you want, making sure that the .addrs line is at the top, right click and Create/Edit Address Region. The top option in the dialog that opens should be "Resize", showing the new end offset and length.

If you don't get the .addrs line selected, it thinks you're trying to create a sub-region, and gets a little bent out of shape if the end straddles an existing end.

FWIW, the docs also note:

There is no affordance for moving the start offset of a region. You must create a new region and then delete the old one.

So you can grow/shrink them but you can't move them.

BacchusFLT commented 1 year ago

Gotcha!

Would say there could be a value in allowing the user to type in the end value. Right click on the .addrs and there have an input field for the end address.

Question was of course triggered from an actual need, and I solved it by deleting and recreating.

BacchusFLT commented 1 year ago

One other aspect of regions (should possibly have it's own item);

On the c64, the disk drive is a totally separate device with it's own CPU, ram, Kernal and the lot. You normally populate the disk drive by having the code in the computer and then write it to the drive ram, over the serial bus.

Using the region function, I can set that chunk of ram as something that is to be executed on another address, but I guess there is no (current) way to avoid that addresses it references are turned into labels in the general program.

Could I pass the suggestion that it would be possible for a region to be more isolated from the general program, having local labels?

In the below, $1c00 is an address in the VIA timer chip of the drive, and not the ram as RAM address $1c00 in the computer. I have refined it as part of a region, so it's in one location of the computer ram, but as you can see, the labels at assuming it's on $0300, so that part works fine.

L035B           ldx   #$f5            ;2
                txs                   ;2
                lda   #$c8            ;2
                jsr   L033B           ;6
                ldx   #$24            ;2
L0365           ldy   L1C00           ;4
                tya                   ;2
                and   #$fc            ;2
                sta   $00             ;3
                dey                   ;2
                tya                   ;2
                and   #$03            ;2
                ora   $00             ;3
                sta   L1C00           ;4
                lda   #$0a            ;2
                jsr   L033B           ;6
                dex                   ;2
                bne   L0365           ;2+
                lda   #$0f            ;2
                jsr   L033B           ;6
fadden commented 1 year ago

Would say there could be a value in allowing the user to type in the end value.

I think that could feel natural if we did text editing within the list view UI element (i.e. the field becomes editable, instead of popping open a dialog box). Might be possible.

Could I pass the suggestion that it would be possible for a region to be more isolated from the general program, having local labels?

This is a significant concern for 65816 code, mostly because of the sheer scope of some of the projects. In that case the project would likely be handled by generating multiple source files and linking the outputs together. That's probably not what you want here.

This situation essentially has two different things at the same address (not really, but the assembler doesn't know that). What makes this unusual is that one of the things is inside the program and one of them isn't. So you'd want some of the code to use the label and other parts of the code to use a project/platform symbol, and we'd need a way to specify which parts of the code use each.

In assembler source you'd have an equate for $1c00 and use that symbol on the operands. Right now in SourceGen you'd need to do something similar, defining a project/platform symbol and setting it explicitly on the operands that reference the "external" address.

The address region stuff provides a measure of label scoping, giving priority to things that are "closer", but it doesn't let you say that parts of the code are completely inaccessible to other parts.

FWIW you can have local labels (prefix with '@' by default), but that mechanism is intended for loops and local branches. We'd need a more general label-scoping mechanism, possibly just a checkbox on the address dialog that says, "nothing in this region can access labels elsewhere, and vice-versa". An exception could be made for labels marked "global, marked for export" so they're not totally isolated.

BacchusFLT commented 1 year ago

Spot on analysis.

In my own case I could rip out the drive code segment and handle that separately, and in this part of the project just make the entire section as junk I guess. But that is not the optimal general approach. A tickbox for making it unavailable, as you said might still be best if it's doable. Possibly a reference to the disk drive, like the main references the main system would be a similar approach.

Den tis 31 jan. 2023 22:04Andy McFadden @.***> skrev:

Would say there could be a value in allowing the user to type in the end value.

I think that could feel natural if we did text editing within the list view UI element (i.e. the field becomes editable, instead of popping open a dialog box). Might be possible.

Could I pass the suggestion that it would be possible for a region to be more isolated from the general program, having local labels?

This is a significant concern for 65816 code, mostly because of the sheer scope of some of the projects. In that case the project would likely be handled by generating multiple source files and linking the outputs together. That's probably not what you want here.

This situation essentially has two different things at the same address (not really, but the assembler doesn't know that). What makes this unusual is that one of the things is inside the program and one of them isn't. So you'd want some of the code to use the label and other parts of the code to use a project/platform symbol, and we'd need a way to specify which parts of the code use each.

In assembler source you'd have an equate for $1c00 and use that symbol on the operands. Right now in SourceGen you'd need to do something similar, defining a project/platform symbol and setting it explicitly on the operands that reference the "external" address.

The address region stuff provides a measure of label scoping, giving priority to things that are "closer", but it doesn't let you say that parts of the code are completely inaccessible to other parts.

FWIW you can have local labels (prefix with '@' by default), but that mechanism is intended for loops and local branches. We'd need a more general label-scoping mechanism, possibly just a checkbox on the address dialog that says, "nothing in this region can access labels elsewhere, and vice-versa". An exception could be made for labels marked "global, marked for export" so they're not totally isolated.

— Reply to this email directly, view it on GitHub https://github.com/fadden/6502bench/issues/139#issuecomment-1411068637, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGZWZSTQT55OIWIF7GT7IZDWVF463ANCNFSM6AAAAAAULWKL4Q . You are receiving this because you authored the thread.Message ID: @.***>

fadden commented 1 year ago

Plan:

Net effect should be to prevent the label finder from seeing the addresses at all, so it will treat address references as external if they're not satisfied locally.

Care should be taken NOT to isolate address region pre-labels, since those are only defined for use by code that does the relocation.

I think that's all we need... reasonably straightforward and low-risk.

EDIT: semi-permeable regions may be useful. Issue #147 has multi-bank code that overlaps; the switching segment's addresses are called locally, but the addresses referenced in the implementation are in the other bank. This could also work for NES Metroid, which has multiple banks at $8000 that are accessed from common code in bank $c000, but the first segment is at $8000 but doesn't support the "API". The first segment still needs to call out to $c000, but shouldn't be used to resolve call-backs.

fadden commented 1 year ago

Added "isolated region" feature to "TO DO" wiki.

BacchusFLT commented 1 year ago

Following our decent discussion and me continuing working on the cartridge project a bit more, I concluded that local labels are great things for making labels not leak out of a particular context and then keep then from colliding with the outside. But the other way around - labels from the outside, leaking in and polluting the disassembly - is likely a bigger problem here. Local labels won't help in that scenario. I take it the solution you are looking at will block leaking in both directions?

My current usecase have a number of routines copied to low mem, and run there. Especially the ones copied to zeropage get totally incomprehensible due to collision with Zeropage usage in other parts of the program. But this is still the same memory space with a lateral difference.

The other part is the number of disk drive routines sent to the drive and executed there. They are contextually different - run in a separate machine (as already mentioned, the disk drive has it's own CPU, timers, RAM and Kernal). So $0400 in the drive is not the same as the $0400 in the computer.

I'm sure it adds a lot of complexlity, but here it could be relevant to open up the thought

fadden commented 1 year ago

The current proposal for the "isolated region" flag is bi-directional. The address-to-offset converter would not search into or out of an isolated region when mapping an address reference to a place in the code.

Defining multiple scopes for symbols can become awkward when generating the assembly output, because all output is written to a single file. Even if the assembler is capable of managing multiple label scopes, I think it would be confusing to have a single file with multiple definitions of a global equate or label. The platform symbols (from .sym65 files) can be overridden with project symbols, but they always have global scope.

The simpler model would be to generate multiple source files, where each one has a separate set of global definitions. That's probably how it was structured in the original source. That would likely be a lot of work on the SourceGen side though.

fadden commented 3 months ago

Now available in pre-release build: https://github.com/fadden/6502bench/releases/tag/v1.9.0-dev1

The address region edit dialog has a pair of checkboxes in the "advanced" section that allow blocking of address resolution inbound and outbound, respectively.