Jump to content
IGNORED

Intellivision Blue/Black Whale Reverse Engineering Report


intvnut

Recommended Posts

I'm finally getting around to posting the Blue Whale / Black Whale reverse engineering document.

The document calls it Black Whale. But, in talking with Steve Roney and Bill Fisher, nobody there remembers any name other than Blue Whale for this device. In any case, there's extensive reverse engineering notes including schematics, commented disassembly, a user's guide, and pictures. All in all, about 100 pages of goodies.

There's one little bit of disassembly on the 6502 side I haven't 100% worked out: The code that stitches the debugger into the KC's menu. The rest, though, is pretty thoroughly understood.

Enjoy!

____________

 

Revision History

  • 2018-04-23, A: Initial public release, immediately withdrawn
  • 2018-04-23, B: Regenerated to fix some last-minute formatting issues.
  • 2018-04-24, A: Corrected descriptions of code that rewinds PC when hitting a breakpoint, and the code that interprets SDBD : xxx@ Rx, R7 when single stepping.

Intellivision_Black_Whale_Reverse_Engineering_Report_20180423b.pdf

Intellivision_Black_Whale_Reverse_Engineering_Report_20180424a.pdf

Edited by intvnut
  • Like 6
Link to comment
Share on other sites

I highly recommend people have a good read of this, it is an excellent piece of work, well worth the time. Another bit of the development tools puzzle is documented and understood.

 

I want to say thanks

  • to Joe and Frank for undertaking the analysis
  • to Joe for taking the time to write up the results
  • to Daniel Bass for lending the boards to study
  • to Intellivision Productions for their pragmatic view on allowing this bit of their IP to be shared

I think that, like the TutorVision study, this is an excellent example of how the community can come together to preserve and share information that is of little commercial value, but of technical interest.

 

Great job, now home in time for tea and medals!

Edited by decle
  • Like 1
Link to comment
Share on other sites

I'm finally getting around to posting the Blue Whale / Black Whale reverse engineering document.

 

The document calls it Black Whale. But, in talking with Steve Roney and Bill Fisher, nobody there remembers any name other than Blue Whale for this device. In any case, there's extensive reverse engineering notes including schematics, commented disassembly, a user's guide, and pictures. All in all, about 100 pages of goodies.

 

There's one little bit of disassembly on the 6502 side I haven't 100% worked out: The code that stitches the debugger into the KC's menu. The rest, though, is pretty thoroughly understood.

 

Enjoy!

 

[Edit: I noticed a minor problem with the first version I posted. Here is the 'B' version.]

Very interesting!!! Great work! :thumbsup:

 

There is one thing I am not clear on: how did the MOS6502 interrupt the CP1610 and trapped breakpoints?

 

Your document seems to suggest that it is just polling on the serial connection, but then how does it detect that a particular breakpoint has been reached and needs to interrupt? Is it using the heretofore unhooked software interrupt line of the CP1610? (Perhaps that's what "SIN" means?)

 

Then again, the document also says that interrupt-driven control was discarded for some reason. I'm a bit confused...

 

Sorry if this seems like a silly question, but I am not a hardware guy. In the past I had posited in this forum how a hardware debugger might work in theory by hooking to the software interrupt line of the CPU, but that would require a modification to the console. From what I could surmise from your document, this is one of the requirements at the beginning during the setup of the environment, no?

 

Perhaps I'm completely off the mark, in which case I would appreciate some guidance. :)

 

dZ.

Link to comment
Share on other sites

Very interesting!!! Great work! :thumbsup:

 

There is one thing I am not clear on: how did the MOS6502 interrupt the CP1610 and trapped breakpoints?

 

Your document seems to suggest that it is just polling on the serial connection, but then how does it detect that a particular breakpoint has been reached and needs to interrupt? Is it using the heretofore unhooked software interrupt line of the CP1610? (Perhaps that's what "SIN" means?)

 

Then again, the document also says that interrupt-driven control was discarded for some reason. I'm a bit confused...

 

Sorry if this seems like a silly question, but I am not a hardware guy. In the past I had posited in this forum how a hardware debugger might work in theory by hooking to the software interrupt line of the CPU, but that would require a modification to the console. From what I could surmise from your document, this is one of the requirements at the beginning during the setup of the environment, no?

 

Perhaps I'm completely off the mark, in which case I would appreciate some guidance. :)

 

dZ.

The 6502 has two interrupt pins, ~NMI and ~IRQ. ~NMI is the 6502 non-maskable interrupt, while ~IRQ is the 6502 maskable interrupt. The serial port can assert ~IRQ to the 6502. It appears initially the software used that approach to handle serial I/O, but later they disabled interrupts on the 6502 and now the 6502 polls the serial port directly.

 

The CP1610 has two interrupt pins, INTR* and INTRM*. INTRM* is connected to the STIC vertical retrace signal. INTRM* is the maskable interrupt pin. INTR* is pulled high by a 5.6KΩ resistor. INTR* is the non-maskable interrupt pin. The Black Whale mod requires you to connect INTR* to PCIT* so that the SIN instruction on the CP1610 triggers a non-maskable interrupt on the CP1610.

 

The 6502 cannot trigger an interrupt on the CP1610.

 

The two processors have their own separate interrupts, and they're handled separately. The 6502 disables interrupts and does everything with polling. The CP1610 operates under the control of whatever game you've loaded, doing EIS/DIS as normal to mask/unmask vertical retrace interrupts. The SIN/SIN2 opcodes trigger a non-maskable interrupt on the CP1610 if you wire the PCIT* pin to the INTR* pin. The breakpoint mechanism in the black whale uses SIN in this manner.

Edited by intvnut
Link to comment
Share on other sites

 

The 6502 has two interrupt pins, ~NMI and ~IRQ. ~NMI is the 6502 non-maskable interrupt, while ~IRQ is the 6502 maskable interrupt. The serial port can assert ~IRQ to the 6502. It appears initially the software used that approach to handle serial I/O, but later they disabled interrupts on the 6502 and now the 6502 polls the serial port directly.

 

The CP1610 has two interrupt pins, *INTR and *INTRM. *INTRM is connected to the STIC vertical retrace signal. *INTRM is the maskable interrupt pin. *INTR is pulled high by a 5.6KΩ resistor. *INTR is the non-maskable interrupt pin. The Black Whale mod requires you to connect *INTR to *PCIT so that the SIN instruction on the CP1610 triggers a non-maskable interrupt on the CP1610.

 

The 6502 cannot trigger an interrupt on the CP1610.

 

The two processors have their own separate interrupts, and they're handled separately. The 6502 disables interrupts and does everything with polling. The CP1610 operates under the control of whatever game you've loaded, doing EIS/DIS as normal to mask/unmask vertical retrace interrupts. The SIN/SIN2 opcodes trigger a non-maskable interrupt on the CP1610 if you wire the *PCIT pin to the *INTR pin. The breakpoint mechanism in the black whale uses SIN in this manner.

Great! Thanks for the response and for clearing it up, it's as I thought (although I had confused some of the pieces, and had some of the terminology wrong). I think I'm clear now.

 

So, my follow question is: what triggers the SIN on the CP1610? I saw that the code compares the interrupted address against the breakpoint list, but what causes it to interrupt?

 

 

UPDATE: if I understand correctly, it's the running program that issues the SIN, right? If so, the program would need to be modified to include these periodically, correct?

Link to comment
Share on other sites

So, my follow question is: what triggers the SIN on the CP1610? I saw that the code compares the interrupted address against the breakpoint list, but what causes it to interrupt?

SIN pulses the PCIT* pin, which is why you need to connect PCIT* to INTR* so that SIN results in a non-maskable interrupt. (SIN2 also.)

Edited by intvnut
Link to comment
Share on other sites

 

SIN pulses the *PCIT pin, which is why you need to connect *PCIT to *INTR so that SIN results in a non-maskable interrupt. (SIN2 also.)

I got that. Perhaps I am not expressing myself adequately, or maybe my question is completely ignorant and has you scratching your head, but what I am trying to understand is where are the SIN instructions located? Are they peppered throughout the game program you are trying to debug?

 

dZ.

Link to comment
Share on other sites

In other news, the Intellivision Wiki states the following about the SIN instruction:

 

"It is unclear if this instruction has any other behaviour, useful or not."

 

That is because the PCIT pin was not connected to anything in an Intellivision.

 

Perhaps if you have a modified Master Component now you can test it thoroughly and expand on it's full specification?

Link to comment
Share on other sites

Regarding your (less important) question at the end of the document whether TV sets in Europe used to have the same two dials: yes, at least for some B&W models. I've got a combo 10" TV, radio, tape recorder that has one dial for VHF channels 5-12 (or perhaps it is VHF 1-12) plus a UHF setting which enables the other dial to tune in UHF 21-69 IIRC. They may not have been entirely common, but appears to have existed.

 

Example image, which I've always assumed to be domestic rather than borrowed from another source:

 

vic20-folkdatorn.jpg

  • Like 1
Link to comment
Share on other sites

I got that. Perhaps I am not expressing myself adequately, or maybe my question is completely ignorant and has you scratching your head, but what I am trying to understand is where are the SIN instructions located? Are they peppered throughout the game program you are trying to debug?

 

dZ.

 

Have a look at the CP1610 side of the debugger, starting at page 74. The commented disassembly goes into extensive detail on how breakpoints are managed (inserting/removing SIN instructions, chasing both sides of conditional branches, when SIN vs. SIN2 gets used, etc). In particular the routines at $8A4A and $8A65.

 

To quote the old Ragu ad: "It's in there!"

Link to comment
Share on other sites

Thank you, I guess I'm too dense to understand it, for I already read the document and posted here. But hey, thanks. *sigh*

 

I apologize for the terse responses. I'm at $DAYJOB replying between meetings.

 

The function at $8A4A (page 85) steps through the breakpoint address list, copying instruction out of the program at the breakpoint addresses to a separate buffer, and replacing them with SIN instructions. This gets called just before running the program. There's a converse function at $8D07 (page 97) that replaces the SIN,1 instructions with the original instructions. Those two functions are fairly simple, and give you basic breakpoint capability

 

The function at $8A65 (pages 85 - 92 (!!)) is for single stepping. It actually tries to decode the length of an instruction, even accounting for conditional branches (finding both legs of the conditional branch), JSRs with data after them (at least for commonly-used EXEC subroutines), and so forth. For instructions that modify R7, it actually modifies the opcode to see what effect the instruction has on R7, so it can single-step over jump tables. It's crazy. The single-step code uses SIN,2 (opcode $37) rather than SIN,1 (opcode $36). The two opcodes both behave the same in the CPU; the different opcodes are there for software to distinguish a breakpoint from a single-step in the interrupt handler. The function at $8D1F (page 97) replaces the SIN,2 instructions with the original instructions.

 

The INTR handler at $8C2B (pages 93-95) decodes whether we hit a breakpoint (SIN,1), the far side of a single-step (SIN,2), or an ordinary interrupt.

 

BTW, while writing this post, I noticed an error in the doc, which I went and fixed in the original Google Doc. This bit is wrong:

.

L_8C62: MVO@    R2,     R3          ; 8C62  This looks like dead code. 
                                    ;       We read R2 from @R3 above, and 
                                    ;       now we write it unmodified to @R3

.

Actually, R2 is modified. It's decremented by 1 at $8C3A. So, I've corrected that to read:

.

L_8C62: MVO@    R2,     R3          ; 8C62  Rewrite the program counter on the
                                    ;       stack to point to the instruction
                                    ;       we had replaced with SIN,1. 

.

 

I'm sure I've made a few other minor flubs here and there. I'm rather embarrassed by that one though. It seems rather obvious in retrospect that if we take an interrupt due to SIN, the saved program counter will point after SIN. To resume at the breakpoint, you need to rewind the PC to point to the SIN instruction and replace it with the original instruction.

Edited by intvnut
Link to comment
Share on other sites

In other news, the Intellivision Wiki states the following about the SIN instruction:

 

"It is unclear if this instruction has any other behaviour, useful or not."

 

That is because the PCIT pin was not connected to anything in an Intellivision.

 

Perhaps if you have a modified Master Component now you can test it thoroughly and expand on it's full specification?

 

As best as I can tell, SIN is fully described in this document: http://spatula-city.org/~im14u2c/chips/CP-1600_Microprocessor_Users_Manual_May75.pdf

 

Flip to pages 13 (description of PCIT* pin), and page 34 (PCIT* Timing).

 

All it really does is pulse the PCIT* pin. That's it. It pulses it in a way that's suitable for tying back to INTR* or INTRM*.

Link to comment
Share on other sites

Will this document help to design an emulator for the Whale Keyboard Component? That's about the only way most people will get to enjoy the system.

 

Not really. Frank and I have been chipping away at it (Frank more than I) for awhile. There's a KC emulator in MAME now that Frank wrote. It doesn't have tape drive support yet, but it will eventually.

Link to comment
Share on other sites

 

I apologize for the terse responses. I'm at $DAYJOB replying between meetings.

 

The function at $8A4A (page 85) steps through the breakpoint address list, copying instruction out of the program at the breakpoint addresses to a separate buffer, and replacing them with SIN instructions. This gets called just before running the program. There's a converse function at $8D07 (page 97) that replaces the SIN,1 instructions with the original instructions. Those two functions are fairly simple, and give you basic breakpoint capability

 

The function at $8A65 (pages 85 - 92 (!!)) is for single stepping. It actually tries to decode the length of an instruction, even accounting for conditional branches (finding both legs of the conditional branch), JSRs with data after them (at least for commonly-used EXEC subroutines), and so forth. For instructions that modify R7, it actually modifies the opcode to see what effect the instruction has on R7, so it can single-step over jump tables. It's crazy. The single-step code uses SIN,2 (opcode $37) rather than SIN,1 (opcode $36). The two opcodes both behave the same in the CPU; the different opcodes are there for software to distinguish a breakpoint from a single-step in the interrupt handler. The function at $8D1F (page 97) replaces the SIN,2 instructions with the original instructions.

 

The INTR handler at $8C2B (pages 93-95) decodes whether we hit a breakpoint (SIN,1), the far side of a single-step (SIN,2), or an ordinary interrupt.

 

BTW, while writing this post, I noticed an error in the doc, which I went and fixed in the original Google Doc. This bit is wrong:

.

L_8C62: MVO@    R2,     R3          ; 8C62  This looks like dead code. 
                                    ;       We read R2 from @R3 above, and 
                                    ;       now we write it unmodified to @R3
.

Actually, R2 is modified. It's decremented by 1 at $8C3A. So, I've corrected that to read:

.

L_8C62: MVO@    R2,     R3          ; 8C62  Rewrite the program counter on the
                                    ;       stack to point to the instruction
                                    ;       we had replaced with SIN,1. 
.

 

I'm sure I've made a few other minor flubs here and there. I'm rather embarrassed by that one though. It seems rather obvious in retrospect that if we take an interrupt due to SIN, the saved program counter will point after SIN. To resume at the breakpoint, you need to rewind the PC to point to the SIN instruction and replace it with the original instruction.

No worries. I appreciate the additional information. It turns out that the part I completely missed (or misunderstood) was this:

 

"The function at $8A4A (page 85) steps through the breakpoint address list, copying instruction out of the program at the breakpoint addresses to a separate buffer, and replacing them with SIN instructions"

 

That is quite clever! :)

 

The single-stepping feature I had understood from your document and impressed me quite a lot! It's very interesting that they are actually simulating each op-code, that's wild!

 

dZ.

Link to comment
Share on other sites

Will this document help to design an emulator for the Whale Keyboard Component? That's about the only way most people will get to enjoy the system.

 

I should shade my previous response: Frank did do some additional circuit tracing work and so forth that has increased our understanding about how the KC operates, and that was inspired by this effort.

 

The Blue(Black?) Whale hardware itself hasn't taught us much more about the KC, but it forced us to learn more about the KC to understand it. Does that make sense?

 

For example, we discovered there's a -5V line that comes to the KC expansion port, and it's a low-current line. You don't want to draw much current from it. We sussed that out from looking at the RS232 line drivers and wondering "Is there a negative voltage on this line?" Frank traced it out....

 

We also determined that ø2 is 895kHz, just like the MC's instruction clock. We needed to know that to determine the BW's baud rate. Frank put the clock signal on a scope and now we know.

 

We also validated that the KC's 6502 EXEC at $C000 - $DFFF seems to get mirrored at $E000 - $FFFF, unless an expansion cartridge claims the address range. Frank traced out those circuits to verify that while I was off reverse engineering the code.

 

Those were all details we could have worked out w/out the BW boards. But with the BW boards in hand, we had more motivation to find those details out sooner rather than later.

Link to comment
Share on other sites

In the interests of accuracy and transparency: I've updated post #1 with a new version. There are two minor changes. First is the error I mentioned in post #13 above.

 

The second involves this little bit of code in the single-step routine:

.

        CMPI    #$0001, R1          ; 8B08  \_ I think this is always taken?
        BNEQ    L_8B2E              ; 8B0A  /

        ;; ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ ;;
        ;;  Not sure the following is reachable. It attempts to execute     ;;
        ;;  an instruction to see what it might do to the target register.  ;;
        ;; ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ ;;

.

It turns out that that code should be reachable if you have SDBD ; xxx@ Rx, R7. So now this snippet reads:

.

        CMPI    #$0001, R1          ; 8B08  \_ Did we arrive here due to SDBD?
        BNEQ    L_8B2E              ; 8B0A  /  (See code at $8BAD.)

        ;; ---------------------------------------------------------------- ;;
        ;;  Based on the code at $8BAD, we arrive here if SDBD modifies an  ;;
        ;;  instruction that isn’t an immediate-mode instruction, but does  ;;
        ;;  modify R7 (given the comparison at $8AF0).                      ;;
        ;; ---------------------------------------------------------------- ;;

.

Other than that, there are no material changes. I did add a Revision History page at the end to track future changes to the document.

Edited by intvnut
  • Like 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...