diff --git a/SourceGen/AppForms/EditProjectProperties.Designer.cs b/SourceGen/AppForms/EditProjectProperties.Designer.cs index cc371d4..37d9481 100644 --- a/SourceGen/AppForms/EditProjectProperties.Designer.cs +++ b/SourceGen/AppForms/EditProjectProperties.Designer.cs @@ -141,9 +141,9 @@ namespace SourceGen.AppForms { this.seekAltTargetCheckBox.AutoSize = true; this.seekAltTargetCheckBox.Location = new System.Drawing.Point(7, 45); this.seekAltTargetCheckBox.Name = "seekAltTargetCheckBox"; - this.seekAltTargetCheckBox.Size = new System.Drawing.Size(130, 17); + this.seekAltTargetCheckBox.Size = new System.Drawing.Size(121, 17); this.seekAltTargetCheckBox.TabIndex = 3; - this.seekAltTargetCheckBox.Text = "Seek alternate targets"; + this.seekAltTargetCheckBox.Text = "Seek nearby targets"; this.seekAltTargetCheckBox.UseVisualStyleBackColor = true; this.seekAltTargetCheckBox.CheckedChanged += new System.EventHandler(this.seekAltTargetCheckBox_CheckedChanged); // diff --git a/SourceGen/AppForms/ProjectView.cs b/SourceGen/AppForms/ProjectView.cs index e16b81c..a3650b0 100644 --- a/SourceGen/AppForms/ProjectView.cs +++ b/SourceGen/AppForms/ProjectView.cs @@ -1021,6 +1021,7 @@ namespace SourceGen.AppForms { mReanalysisTimer.StartTask("Generate DisplayList"); mDisplayList.GenerateAll(); mReanalysisTimer.EndTask("Generate DisplayList"); + UpdateSelectionHighlight(); } #endregion Project management diff --git a/SourceGen/Examples/Tutorial/Tutorial2 b/SourceGen/Examples/Tutorial/Tutorial2 new file mode 100644 index 0000000..222f439 Binary files /dev/null and b/SourceGen/Examples/Tutorial/Tutorial2 differ diff --git a/SourceGen/Examples/Tutorial/Tutorial2.S b/SourceGen/Examples/Tutorial/Tutorial2.S new file mode 100644 index 0000000..dae5c7a --- /dev/null +++ b/SourceGen/Examples/Tutorial/Tutorial2.S @@ -0,0 +1,87 @@ +; Copyright 2018 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Assembler: Merlin 32 + +INPUT equ $3000 +OUTPUT equ $0400 +PTR1 equ $02 +PTR2 equ $04 + +START equ $2000 + org START-2 + + dw START + + sec + ror A + bmi skipstr + +string0 asc 'first string',00 +string1 asc 'another string',00 +string2 asc 'string the third',00 +string3 asc 'last string',00 + +skipstr + lda #stringtab + sta PTR1+1 + + jsr thing + and #$03 + asl A + tay + lda (PTR1),y + sta PTR2 + iny + lda (PTR1),y + sta PTR2+1 + + ldy #$ff +]loop iny + lda (PTR2),y + beq copydone + ora #$80 + sta OUTPUT,y + bne ]loop ;always taken + +stringtab + dw string0 + dw string1 + dw string2 + dw string3 + +copydone + lda #$ff + sta _mod+1 +_mod lda #$00 + bne skipbrk + +middat ds 4 +outdat ds 1 + +skipbrk + lda middat + ora middat+1 + and middat+2 + eor middat+3 + + ldx #$00 + dfb $2c +rebr ldx #$01 + sta outdat + lda INPUT + lsr A + lsr A + lsr A + lsr A + sta INPUT + bne rebr + + rts + +thing + lda INPUT + rts + diff --git a/SourceGen/RuntimeData/Help/intro.html b/SourceGen/RuntimeData/Help/intro.html index ec0b98b..6f4f15b 100644 --- a/SourceGen/RuntimeData/Help/intro.html +++ b/SourceGen/RuntimeData/Help/intro.html @@ -636,7 +636,7 @@ L1005 EOR #$00

If you really don't like the way this works, you can disable the -search for alternate targets entirely from the +search for nearby targets entirely from the project properties. Self-modifying code will always be adjusted because of the limitation on mid-instruction labels.

diff --git a/SourceGen/RuntimeData/Help/settings.html b/SourceGen/RuntimeData/Help/settings.html index 7a141db..31fd099 100644 --- a/SourceGen/RuntimeData/Help/settings.html +++ b/SourceGen/RuntimeData/Help/settings.html @@ -176,7 +176,7 @@ entry point hint) will use this value. This is chiefly of use for identify strings and regions filled with a single byte value. If it's not checked, anything that isn't detected as code or explicitly formatted will simply be shown as a byte value.

-

If "seek alternate targets" is checked, the analyzer will try to use +

If "seek nearby targets" is checked, the analyzer will try to use nearby labels for data loads and stores.

The "minimum characters for string" setting determines how many ASCII characters need to appear consecutively for the data analyzer to diff --git a/SourceGen/RuntimeData/Help/tutorials.html b/SourceGen/RuntimeData/Help/tutorials.html index b6e7e68..cbb6294 100644 --- a/SourceGen/RuntimeData/Help/tutorials.html +++ b/SourceGen/RuntimeData/Help/tutorials.html @@ -195,7 +195,7 @@ it and check the References window.)

comment, and hit Enter. Your comment appears in the "comment" column.

-

Editing Operands

+

Editing Instruction Operands

The operand in the LDA instruction at line $2000 refers to an address ($3000) that isn't part of the file. We want to create an equate directive to @@ -239,7 +239,7 @@ symbolic reference, there's another option in the Edit Operand dialog that does it.)

-

Editing Data Formats

+

Editing Data Operands

There's some string and numeric data down at the bottom of the file. The final string appears to be multiple strings stuck together. Notice that @@ -247,8 +247,10 @@ the opcode for the very last line is '+', which means it's a continuation of the previous line. Long data items can span multiple lines, split every 64 characters (including delimiters), but they are still single items: selecting any part selects the whole.

-

Select the last line, then Edit > Edit Data Format. At the top of the -dialog that appears, it will say "65 bytes selected". You can format this +

Select the last line, then Actions > Edit Operand. You'll notice +that this dialog is much different from the one you got when editing the +operand of an instruction. At the top it will say "65 bytes selected". You +can format this as a single 65-byte string, as 65 individual items, or various things in between. For now, select "Single bytes", and then on the right, select "ASCII". Click "OK".

@@ -256,8 +258,8 @@ select "ASCII". Click "OK".

same set of addresses.

Select address $203D on its own, then Actions > Edit Label. Set the label to "STR1". Move up a bit and select address $2030, then scroll to -the bottom and shift-click address $2070. Select Actions > Edit Data -Format. At the top it should now say, "65 bytes selected in 2 groups". +the bottom and shift-click address $2070. Select Actions > Edit Operand. +At the top it should now say, "65 bytes selected in 2 groups". There are two groups because the presence of a label split the data into two separate regions. Select "mixed ASCII and non-ASCII", then click "OK".

@@ -274,7 +276,7 @@ Format (or hit Ctrl+B).

The data starting at $2025 appears to be 16-bit addresses that point into the table of strings, so let's format them appropriately.

Select the line at $2025, then shift-click the line at $202E. Select -Actions > Edit Data Format. If you selected the correct set of bytes, +Actions > Edit Operand. If you selected the correct set of bytes, the top should say, "10 bytes selected". Click the "16-bit words, little-endian" radio button, then over to the right, click the "Address" radio button. Click "OK".

@@ -307,12 +309,10 @@ it should always match exactly.)

Click "Close" to close the window.

-

Go Forth

+

End of Part One

-

That's it for the basic tutorial. Play with the program some more to see -what it can do, or do something wild like read the manual.

-

While you can do some fancy things, nothing you do will alter the -data file. The assembled output will always match the original.

+

At this point you know enough to work with a SourceGen project. Continue +on to the next tutorial to learn more.

Advanced Features

@@ -390,8 +390,161 @@ code entry point hint -- but did several of them at once.

SourceGen asks if you want to continue, click OK.

-

[to be continued]

+

Going Deeper

+

Start a new project. Select "Generic 6502". For the data file, navigate +to the Examples directory, then from the Tutorials directory +select "Tutorial2".

+

The first thing you'll notice is that we immediately ran into a BRK, +which is a pretty reliable sign that we're not in a code section. The +generic profile puts a code entry point hint on the first byte, but that's +wrong here. This particular file begins with 00 20, which +could be a load address (C64 binaries look like this). So let's start +with that assumption.

+

Click on the first line of code at address $1000, and select +Actions > Remove Hints. The $20 got absorbed into a string. The string +is making it hard to manipulate the next few bytes, so let's fix that by +selecting Edit > Toggle Data Scan. This turns off the feature that +looks for strings and .FILL regions, so now each uncategorized byte is +on its own line.

+

Select the first two lines, use Actions > Edit Operand, and format +it as a 16-bit little-endian word. We're assuming this is the load +address for the data that follows, so click on the line with address +$1002, select Actions > Set Address, and enter "2000". With that +line still selected, use Actions > Hint As Code Entry Point to identify +it as code.

+

That looks better, but it's branching off the bottom of the screen +(unless you have a really tall screen or small fonts) because of all the +intervening data. Use Edit > Toggle Data Scan to turn the string +finder back on.

+ +

There are four strings starting at address $2004, each of which is +followed by $00. These look like null-terminated strings, so let's make +it official. But first, let's do it wrong. Click on the line with +address $2004 to select it. Hold the shift key down, then double-click +on the operand field of the line with address $2031 (i.e. click on +"last string").

+

The Edit Data Format dialog opens, but the null-terminated strings +option is not available. This is because we didn't include the null byte +on the last string. To be recognized as one of the "special" string types, +every selected string must match the expected pattern.

+

Cancel out of the dialog. Hold the control key down, and double-click +on the operand on line $203c ($00). Control-clicking adds the line to +the selection, and double-clicking the operand reopens the dialog. You +should see "Null-terminated strings (4)" as an available option now. Click +on that, then click OK. The strings are now shown as .ZSTR.

+ +

It's wise to save your work periodically. Use File > Save to create +a project file for Tutorial2.

+ +

Pointers and Parts

+ +

Let's move on to the code at $203d. It starts by storing a couple of +values into direct page address $02/03. This appears to be setting up a +pointer to $2063, which is a data area inside the file. So let's make it +official.

+

Select line $2063, and use Actions > Edit Label to give it the +label "XDATA". Now edit the operand on line $203d, and set it to the +symbol "XDATA", with the part "low". Edit the operand on line $2043, +and set it to "XDATA" with the part "high". (Note the symbol text box +gets focus immediately, so you can start typing the symbol name as soon +as the dialog opens; you don't need to click around first.) If all +went well, the operands should now read LDA #<XDATA +and LDA #>XDATA.

+

Let's name the pointer. Edit the operand on line $203f, enter the +symbol "PTR1", and in the Symbol Shorcuts section, click "Set operand +AND create project symbol". Click OK. Note that operand on line $2043 +has changed to "PTR1+1".

+

Double-click on the JSR on line $2045 to jump to L209A. This just +loads a value from $3000 into the accumulator and returns, so not much +to see here. Hit the back-arrow in the toolbar to jump back to the JSR.

+

The next bit of code masks the accumulator so it holds a value between +0 and 3, then doubles it and uses it as an index into PTR1. We know PTR1 +points to XDATA, which looks like it has some 16-bit addresses. The +values loaded are stored in two more zero-page locations, $04-05.

+

$04 is being displayed as "PTR1+2", which isn't quite right, so let's +fix that. Double-click on the operand of address $204e, set the symbol +to "PTR2", and again click "Set operand AND create project symbol". +Click OK. That looks better.

+ +

The next bit of code copies bytes from PTR2 to $0400, stopping when it +hits a zero byte. Looks like this is copying null-terminated strings. +This confirms our idea that XDATA holds 16-bit addresses, so let's +format it. Select lines $2063 to $2066, and Actions > Edit Operand. +It should say "8 bytes selected" at the top. Select "16-bit words, +little-endian", and then from the Display As box, select "Address". +Click OK. If you scroll up, you'll see that your .ZSTR strings now have +labels that match the labels in XDATA.

+

Now that we know what XDATA holds, let's rename it. Change the label +to STRADDR. The symbol parts in the operands at $203d and $2041 update +automatically.

+ +

Let's pause briefly to look at the cycle-count feature. Use +Edit > Settings to open the app settings panel, then select the +Asm Config tab. Click the "Show cycle counts" checkbox, then click OK.

+

Every line with an instruction now has a cycle count on it. The cycle +counts are adjusted for everything SourceGen can figure out. For example, +the BEQ on line $205a shows "2+" cycles, meaning that it takes at least two +cycles but might take more. That's because conditional branches take an +extra cycles if the branch is taken. The BNE on line $2061" shows 3 cycles, +because we know that the branch is always taken.

+

The cycle-count comments are included in assembled output as well. If +you add an end-of-line comment, it appears after the cycle count.

+

Hit Ctrl+S to save your project. Make that a habit.

+ +

Odds & Ends

+ +

The rest of the code isn't really intended to do anything useful. It +just exists to illustrate some odd situations.

+

Look at the code starting at $206b. It ends with a BRK at $2074, which +as noted earlier is a bad sign. If you look up two lines, you'll see that +it's loading the accumulator with zero, then doing a BNE, which should never +be taken (note the cycle count for the BNE is 2). The trick is in the +two lines before that, which use self-modifying code to change the LDA +immediate operand from $00 to $ff. The BNE is actually a branch-always.

+

We can fix this by correcting the status flags. Select line $2072, +and then Actions > Override Status Flags. This lets us specify what +the flags should be before the instruction is executed. For each flag, +we can override the default behavior and specify that the flag is +clear (0), set (1), or indeterminate (could be 0 or 1). In this case, +we know that the self-modified code will be loading a non-zero value, so +in the "Z" column click on the button in the "Zero" row. Click OK. The +BNE is now an always-taken branch, and the code list rearranges itself +appropriately (and the cycle count is now 3).

+ +

Continuing on, the code at $2079 touches a few consecutive locations. Edit +the label on line $2074, setting it to "VAR". Notice how the references +to $2074 through $2077 have changed from auto-generated labels to +references to VAR. For some projects this may be undesirable. Use +Edit > Project Properties, then in the Analysis Parameters box +un-check "Seek nearby targets", and click OK. You'll notice that the +references to $2075 on have switched back to auto labels. Furthermore, if +you scroll up, you'll see that the stores to PTR1+1 and PTR2+1 are now +just stores to $03 and $05.

+

The nearby-target behavior is generally desirable, because it lets you +avoid explicitly labeling every part of a multi-byte data item. For now, +use Edit > Undo to turn it back on.

+ +

The code at $2085 looks a bit strange. LDX, then a BIT with a weird +symbol, then another LDX. If you look at the "bytes" column, you'll notice +that the three-byte BIT instruction has only one byte on its line. The +trick here is that the LDX #$01 is embedded inside the BIT +instruction. When the code runs through here, X is set to $00, then +the BIT instruction sets some flags, then the STA runs. Several lines +down there's a BNE to $2088, which is in the middle of the BIT instruction. +It loads X with $01, then also continues to the STA.

+

Embedded instructions are unusual but not unheard-of. When you see the +extra symbol in the opcode field, you need to look closely at what's going +on.

+ + +

Go Forth

+ +

That's it for the tutorials. There's significantly more detail on +all aspects of SourceGen in the manual.

+

While you can do some fancy things, nothing you do will alter the +data file. The assembled output will always match the original. So +don't be afraid to play around.