My 6502 Disassembly Project

Thanks. But I already have that and am trying to wrap my head around it.

Which assembler is compatible with gold-wings.a65?

If your intent is to be able to make a modified version of the code, we should strive to maintain a documented and buildable set of source code.

Remember that link I shared from flipprojets.fr a while back (the one with all the gawdy 3D chicks in bathing suits :stuck_out_tongue: ) In there they mention a Rockwell ā€œDesign Centerā€, which I believe relates to the Rockwell AIM-65 development computer, hence the .a65 extension. Iā€™m assuming an AIM-65 would be difficult to get a hold of now and probably not even as nice as modern systems, so all we need to do is find a compatible assembler.

However, we already have the disassembly; in my n00b view of things, couldnā€™t we just put that into any assembler worth its salt and get the magic machine code? Itā€™s been a long time since Iā€™ve done this, and it was with an Intel 8051 where we wrote the assembly from scratch instead of being given code to play with first.

More details from me once Letā€™s Play Gaming Expo has passed.

Oh, and besides the datasheet Walter mentioned at 6502.org, hereā€™s another helpful one for the 6532 RIOT chip: http://pdf.datasheetcatalog.com/datasheets/480/501467_DS.pdf

Rockwell made 6502 processors for awhile, but no more.

The Western Design Center http://www.westerndesigncenter.com/wdc/index.cfm is still doing business with the 6502 architecture. They do not offer a free assembler though their paid product is not bad at $40, but it is tied to your MAC address so you will need multiple ā€œcopiesā€ if you use more than one computer.

There is a long list of assemblers at http://6502.org/tools/asm/

In my experience, there is quite a variation as to what pseudo ops they honor, such as .byte vs db vs fcb.

I asked because I thought you might already be using one.

Iā€™m afraid that I have been spending more time on my projects than yours.

The debugger/simulator rabbit hole is connected to the cross assembler one and I now have mine assembling the Gold Wings code except for a phase error problem.

A phase error is flagged when a value determined for a symbol in pass 1 does not match during phase 2. It usually means there is a flaw in the assembler dealing with forward references though the source code can sometimes be transformed to avoid the error.

I have isolated the problem to a very simple test file:

[code]
DEI Research 6502 Cross Assembler Version 0.0 Jun-19-2016 16:04:11 Page 1
test.a65

Addr Code Line# Source Statement

0200 00001 *= $200
00002
0200 4D 0402 00003 eor Forward
0203 45 00 00004 eor Backward
00005
0205 00006 Forward
*** Error 12 *** Phase error between passes
00007
0000 00008 *= 0
00009
0000 00010 Backward
00011
00012 end
DEI Research 6502 Cross Assembler Version 0.0 Jun-19-2016 16:04:11 Page 2
test.a65 - Symbol table

Symbol Value Line Attributes

BACKWARD . . . . . . . . . . . . 0000 00010
FORWARD . . . . . . . . . . . . 0204 00006
[/code]

The assembler tries to use zero page addressing whenever possible to save code space and CPU cycles.

When it encounters the reference to Forward during pass 1, it does not know the value yet. Unfortunately, my code has a default value of 0, so two bytes are allocated for the zero page form of the instruction. In pass 2, it is clear the address is not in the zero page, so the absolute (3 byte) form is assembled, causing the location counter to be off by one byte - hence the phase error.

That Backward nonsense is a perverse test for an improper fix to the forward reference problem. In pass 1, 3 bytes should be allocated for the absolute form because of the forward reference. In pass 2, the absolute form must be assembled even though the zero page form is both possible and preferable in order to avoid a phase error the other way.

An ideal solution is an ā€œoptimizingā€ assembler which makes as many passes as necessary to resolve everything. Unfortunately, my code is not structured to be able to do that efficiently.

A common compromise is to provide a way to give the assembler a hint in the source code as to which form to use. For example,

	eor	>Forward
	eor	<Backward

Again, unfortunately, my code is not set up to do that easily.

I have not fixed the phase error problem yet, but since I am so close, I temporarily disabled that little bit of code at the bottom of the assembler to delete the object code file if there were errors. I love having my own tools so that I can do thatā€¦

I loaded the binary into my debugger/simulator and did a hex dump. As I suspected from looking at that big mash of mixed data and instructions, there are more text strings:

L20E5:	.byte	"TEST MODE"

L20EF:	.byte	"LEFT CHUTE COINS"

L2100:	.byte	"RIGHT CHUTE COINS"

L2112:	.byte	"CENTER CHUTE COINS"

L2125:	.byte	"TOTAL PLAYS"

L2131:	.byte	"TOTAL REPLAYS"

L213F:	.byte	"REPLAY PERCENTAGE"

L2151:	.byte	"TOTAL EXTRA BALLS"

L2163:	.byte	"TOTAL TILTS"

L216F:	.byte	"SPECIALS"

L2178:	.byte	"TIMES HGTD AWARDED"

L218B:	.byte	"FIRST HIGH SCORE"

L219C:	.byte	"SECOND HIGH SCORE"

L21AE:	.byte	"THIRD HIGH SCORE"

L21BF:	.byte	"HIGHEST GAME TO DATE"

L21D4:	.byte	"AVERAGE PMAYING TIME"	; <sic>

L21E9:	.byte	"LAMP!TEST"

L21F3:	.byte	"LAMP+SOLENOID TEST"

L2207:	.byte	"SWITCH MATRIX TEST"

L221A:	.byte	"DIP SWITCH SETTINGS"

L222E:	.byte	"DISPLAY TEST"

L223B:	.byte	"MEMORY TEST"

L227D:	.byte	"SWITCH    CLOSED"

L228E:	.byte	"ALL SWITCHES OPEN"

L22A0:	.byte	" -MIN  O-SEC"

L22AD:	.byte	"LAMP"

L22B4:	.byte	"SOLENOID"

L22BF:	.byte	"BOOKKEEPJNG CLEARED"	; <sic>

L22D3:	.byte	"*SEE SERVICE MANUAL*"

L22ED:	.byte	"0123456789ABCDEF"

L2300:	.byte	"ERROR- U4"

L230A:	.byte	"ERROR- U5"

L2314:	.byte	"ERROR- U6"

L231E:	.byte	"ERROR- Z5"

L2328:	.byte	"ERROR- GAME PQOM 1"

L233B:	.byte	"ERROR- GAME PSOM.2"

L234E:	.byte	"GAME PSOM CHECK-SUM"

L2362:	.byte	"PROM 1-   "

L236F:	.byte	"ENTER INITIALS  (6O)"

L2384:	.byte	"PKAYER .-A  "

L239C:	.byte	"SQUADRON LEADERS  "

L24A2:	.byte	"*** RED ALERT ***"

L24B4:	.byte	"FLIGHT QUARTERS"

So as you can see, we cannot hope to just decipher and comment what the disassembler spits out.

Edit: I had the thought over dinner that the misspellings in some of the text may be due to the disassembler converting portions of the text into instructions which were in turn improperly reconstructed by my assembler due to the phase errors. This is apparent not the case as I fixed the phase error and see exactly the same text as before.

1 Like

Looking closely at my listing, I noticed a byte missing between the labels L20A0 and L20B2:

.209D 33		  00384	L209D:      .byte $33
.209E 35 37		  00385	            and L0037,X
.20A0 B1 BE		  00386	L20A0:      lda (L00BE),Y
.20A2 CB		  00387	            .byte $CB
.20A3 D8		  00388	            cld
.20A4 E5 B7		  00389	            sbc L00B7
.20A6 C4 D1		  00390	            cpy L00D1
.20A8 DE EB33		  00391	            dec L33EB,X
.20AB 35 37		  00392	            and L0037,X
.20AD 35 30		  00393	            and L0030,Y
.20AF 00 00		  00394	            .byte $00,$00
.20B1 00 00 00		  00395	L20B2:      .byte $00,$00,$00
.20B4 20 2020		  00396	            jsr L2020
.20B7 00 04		  00397	L20B8:      .byte $00,$04

After verifying that my assembler was not the culprit dropping the byte, I put on my hacker cap and plunged on. Not having the original binary, I figured there had to be a copy stashed within gold-wings.wrk for the disassembler to munch on. So, hex dump time. And here is the corresponding section:

00011930: 80 00 06 0C 12 33 35 37-B1 BE CB D8 E5 B7 C4 D1  |.....357........|
00011940: DE EB 33 35 37 39 30 00-00 00 00 00 00 20 20 20  |..35790......   |
00011950: 00 04 08 0C 10 14 17 1A-1D 20 08 10 15 20 81 82  |......... ... ..|

OK, my assembler has a bug displaying EB33 instead of 33EB in the object code section of the listing but there is no mistaking that 39 30 00 has been replaced by 35 30.

Now why would that be?

Well,

35 30	->	and	30,Y

while

39 30 00	->	and	0030,Y

Yepā€¦absolute versus zero page as I was discussing earlier.

The solution? If it is not actual code, use .byte instead of fake instructions.

Folks, letā€™s have a meeting to discuss progress and learn from each other sometime this weekend. Bill, Iā€™d love to see how youā€™ve been doing all this stuff. Please get back to me ASAP on what times youā€™re available by using this link: http://www.needtomeet.com/meeting?id=b7p2e2eiV Whoever wants to join is welcome, but Iā€™ll pick the time with the most participants say they can make it.

First the bad news, for me anyway: crow is not very tasty.

The good: I was so obsessed with the X indexing modes that I failed to realize the ZeroPage,Y mode is only available for the LDX and STX instructions. He who lives by the table shall die by the table. Fixed that and the text cleared right up. I will update the list of text strings above shortly.

However, there are other bytes being dropped later on, in real code. So I have more analysis to do.

Interestingā€¦I cannot edit the earlier post containing the list. I could have sworn there was no time limit in the past.

Anyway, this is the corrected text string list:

L20E6:	.byte	"TEST MODE"
L20F0:	.byte	"LEFT CHUTE COINS"
L2101:	.byte	"RIGHT CHUTE COINS"
L2113:	.byte	"CENTER CHUTE COINS"
L2126:	.byte	"TOTAL PLAYS"
L2132:	.byte	"TOTAL REPLAYS"
L2140:	.byte	"REPLAY PERCENTAGE"
L2152:	.byte	"TOTAL EXTRA BALLS"
L2164:	.byte	"TOTAL TILTS"
L2170:	.byte	"SPECIALS"
L2179:	.byte	"TIMES HGTD AWARDED"
L218C:	.byte	"FIRST HIGH SCORE"
L219D:	.byte	"SECOND HIGH SCORE"
L21AF:	.byte	"THIRD HIGH SCORE"
L21C0:	.byte	"HIGHEST GAME TO DATE"
L21D5:	.byte	"AVERAGE PLAYING TIME"
L21EA:	.byte	"LAMP TEST"
L21F4:	.byte	"LAMP+SOLENOID TEST"
L2208:	.byte	"SWITCH MATRIX TEST"
L221B:	.byte	"DIP SWITCH SETTINGS"
L222F:	.byte	"DISPLAY TEST"
L223C:	.byte	"MEMORY TEST"
L227E:	.byte	"SWITCH    CLOSED"
L228F:	.byte	"ALL SWITCHES OPEN"
L22A1:	.byte	" -MIN  O-SEC"
L22AE:	.byte	"LAMP- "
L22B5:	.byte	"SOLENOID- "
L22C0:	.byte	"BOOKKEEPING CLEARED"
L22D4:	.byte	"*SEE SERVICE MANUAL*"
L22ED:	.byte	"0123456789ABCDEF"
L2301:	.byte	"ERROR- U4"
L230B:	.byte	"ERROR- U5"
L2315:	.byte	"ERROR- U6"
L231F:	.byte	"ERROR- Z5"
L2329:	.byte	"ERROR- GAME PROM 1"
L233C:	.byte	"ERROR- GAME PROM.2"
L234F:	.byte	"GAME PROM CHECK-SUM"
L2363:	.byte	"PROM 1-   "
L2370:	.byte	"ENTER INITIALS  (6O)"
L2385:	.byte	"PLAYER  -A  "
L239D:	.byte	"SQUADRON LEADERS  "
L24A3:	.byte	"*** RED ALERT ***"
L24B5:	.byte	"FLIGHT QUARTERS"

Answered via the link. Basically Saturday 5 to 10. If I come in Sunday, I may want to go to the board meeting. I also plan to be at Dwightā€™s meeting tonightā€¦

My favourite kind!

(Maybe thereā€™s something wrong with meā€¦)

1 Like

The two missing bytes later in the file are the result of more absolute versus zero page addressing mode issues:

3CBE ldx L006D

3D1F lda L006D

The naive answer is to move the equate for this label to the end of the file to force absolute mode due to forward reference. But other instructions, like

2677 sta L006D

use zero page addressing.

So we are going to need an assembler which allows us to force the addressing mode.

Iā€™ve submitted a meeting on the DMS Calendar for this Saturday 6/25 at 5:15 PM in the conference room so we can discuss this further. For instance, the DIS6502 showed me all those strings from $20E5 to $24C2, and I havenā€™t found any more other than *** TILT ***. I havenā€™t seen anything that references these addresses directly, so it must be loading these in with some sort of indexed memory offset.

Also Bill, Iā€™ll be at the Space on Tuesday from 6:30-9, and will be available at maybe 8 or so to talk about this more in person.

Itā€™d be neat to find a simulator that could handle the RIOT chips and see what theyā€™re doing. Plugging this into a general-purpose simulator might get pretty weird unless itā€™s highly configurable. Of course, itā€™d be cool if it knew how the VFD driver worked and could actually display the output on-screen. :wink: Otherwise, without the ability to input anything to the RIOT chips, I bet youā€™d only ever see the outputs flash by pertaining to driving the attract mode on the display rather than playing a game.

Iā€™ll be in Tuesday for the Android Programming class. How late I can stay will depend on the result of a phone call I cannot make until after 5 to see whether I need to report for jury duty Wednesday morning.

I have been looking at the schematic. Is the VFD hooked up to that latch hanging off of U5? If so, L2ADD may be the routine to send a byte to the VFD:

.2ADD 48		  01642	L2ADD:      pha			; Save byte
.2ADE 09 30		  01643	            ora #$30		; LD1 and LD2 high
.2AE0 29 3F		  01644	            and #$3F
.2AE2 8D 0282		  01645	            sta RIOTU5_R2_DRB	; Output to latch
.2AE5 A9 10		  01646	            lda #$10		; Latch low nybble
.2AE7 8D 0280		  01647	            sta RIOTU5_R0_DRA
.2AEA A9 00		  01648	            lda #$00
.2AEC 8D 0280		  01649	            sta RIOTU5_R0_DRA
.2AEF 68		  01650	            pla			; Recover byte
.2AF0 20 277B		  01651	            jsr L277B		; shift upper nybble to lower
.2AF3 09 30		  01652	            ora #$30		; LD1 and LD2 high
.2AF5 8D 0282		  01653	            sta RIOTU5_R2_DRB	; Output to latch
.2AF8 A9 20		  01654	            lda #$20		; Latch upper nybble
.2AFA 8D 0280		  01655	            sta RIOTU5_R0_DRA
.2AFD A9 00		  01656	            lda #$00
.2AFF 8D 0280		  01657	            sta RIOTU5_R0_DRA
.2B02 A5 6F		  01658	            lda L006F		; Do not know what this contains
.2B04 8D 0282		  01659	            sta RIOTU5_R2_DRB
.2B07 EA		  01660	            nop
.2B08 EA		  01661	            nop
.2B09 A9 30		  01662	            lda #$30		; LD1 and LD2 high
.2B0B 8D 0282		  01663	            sta RIOTU5_R2_DRB
.2B0E 60		  01664	            rts

I have not been able to figure where the data is coming from yet.

I have just cracked where it tends to write various messages to the display. Check out my Wiki page on L315A. It seems to write 20 characters to the first row [$13, $26], and then can do another 20 characters on the second row [$27, $3A]. However, it also seems to have another display ā€œpageā€ it may evidently choose to switch to later as youā€™ll also see characters written to [$3B, $4E] and [$4F, $62]. This is based on the hard-coded 0x13 used in a zero-page indirect STA instruction, and how X is usually set to 0, 0x14, 0x28, or 0x3C before this subroutine gets called.

I stumbled upon this by total happenstance as I was trying to move code blocks into their own pages and just happened to be curious as to how many times the next label after the preceding JMP or RTS was called. I knew it had to be something good when this was referred to almost 20 times in the code!

1 Like

I think those memory locations you reference are memory buffers where the display contents are formatted before it is sent to the actual display hardware.

Each RIOT contains 128 bytes of 8-bit RAM. According to the schematic, they are mapped to $0000ā€¦$017F.

Hence the stack pointer is loaded with $7F because only half of the stack space has memory in it. The rest of the RAM make up the zero page.

While hardware can be mapped into the zero page, the schematic shows no signs of that. I am still looking at it, but there are indications of code looking at buffers at $00, $28 and $3C using L0070 and L0071 as pointers and blasting their contents to those D flip-flops via the U5 RIOT - I still think that is where the VFD electrically resides.

There is another RAM chip, but it looks to be only 4 bits wide and I have not looked to see where it is mapped.

1 Like

Just wanted to say it: you guys are awesome for documenting your reverse-engineering effort!

4 Likes