Debugging a C64 problem with Hardware Monitor?

Caution: Non registered users only see threads and messages in the currently selected language, which is determined by their browser. Please create an account and log in to see all content by default. This is a limitation of the forum software.


Also users that are not logged in can not create new threads. This is a, unfortunately needed, counter measure against spam. Please create an account and log in to start new threads.

Don't Panic. Please wash hands.
  • I find myself in a situation where my program works well on the VICE emulator, but fails on an actual C64 when the execution reaches a certain point.


    I would like to use Turbo Chameleon 2's Hardware Monitor to debug the issue on C64. I got a little bit familiar with VICE's Monitor, and found its "until", "next", "bt" and "z" commands quite helpful.


    Looking at Turbo Chameleon's documentation, I see that its Monitor does not have the same or similar commands. Is there a way that I could add a hardware breakpoint for until execution reaches a certain Instruction Pointer address value, and then break to Monitor, where I would then be able to single step execution forwards until I observe the bug?


    Thanks!

  • This would require a core change to make a breakpoint, and on top, single-stepping the CPU is using the CIA hardware on all monitors I know. You probably don't want that, but truly halt the rest of the hardware, too.


    This would not work when it's in cartridge mode, where Chameleon synchronizes to the existing VIA/CIA hardware. I could only see a "full stop" of the complete hardware (like in VICE) if you use the Chameleon in stand-alone mode. Since the monitor program in Chameleon runs on the actual Chameleon hardware, this would also imply a debugger/monitor program that would have to connect through USB to the Chameleon. TBH, that's such a big chunk to develop, I don't think it even fits the core any more. This may be a nice-to-have-thing for the C64 Reloaded MK3, though.


    That said, is your program working in stand-alone mode, that is, without C64? This may already give enough hints on where to look for your bug.


    Jens

  • As Jens said, this is not really possible - The monitor in the chameleon menu is basically like the monitor in a freezer cartridge, with similar limitations.


    That said, VICE has become really damn accurate by now - so cases where a program runs in VICE, but not on the real thing, can usually be boiled down to the same reasons that would cause problems on different real C64s too:


    - "old" vs "new" CIA. That's the easiest to test, just choose the other model in VICE.

    - use of uninitialized RAM. This is a bit harder to test - but you can change the "RAM reset pattern", or fill the entire ram with 0s or FFs before loading your program (caution: for these tests make sure NOT to use autostart in VICE, load the program manually)


    And also use a recent Development build of VICE, because you never know: https://github.com/VICE-Team/svn-mirror/releases

  • Thanks for the details.


    I think I found the issue that causes a divergence compared to VICE. It is two separate divergences actually.


    In my application, I freeze-snapshot the state of the C64 RAM into REU ($0000 - $C7FF and $D000-$DC03), then load in another subprogram, and when that subprogram is finished, I load the original program back to resume its execution. (i.e. a "parent-child subprogram" invocation type of use case )


    So to save the C64 memory, I point REU memcpy start address to 0 on both RAM and REU sides, and transfer length to C7FF, and kick off a transfer. (and then do the same for $D000-$DC03).


    This implementation works on VICE, and for a while it seemingly worked on my C64 with TC2+RR-Net in it, but then when I started adjusting my CPU Processor Port map at address $0001, it looks like that is where things started to diverge between VICE and C64+TC2.


    The first divergence I see is that in Turbo Chameleon 2 Hardware Monitor, when one types "m 0", the monitor always displays 00 00 for the first two bytes of the address space, and not the actual CPU Processor Port Data Direction and Processor Port map register values.



    VICE does not do this. Instead it shows the values of the Processor Port Data Direction registers at $0000 (default value $2F) and the Processor port bits at $0001 (which I've customized to a value $3F in my program here), i.e.



    The second divergence is similar.

    In VICE, it works out ok to use the REU to copy $0000-$C7FF from RAM to REU (and then back). The values of addresses $0000 and $0001 are also read and written, so even if the "child" program had changed the value of Processor Port at $0001, the copy back from REU to RAM will first restore the earlier memory map that was in effect while the first memory snapshot was taken, and then the rest of the memory read will fall into place.


    On a real C64 with TC2's REU, this does not work. Further prodding the scenario, it looks like when TC2 REU is used to read the first two bytes of the C64 over to the REU, it will always populate the REU memory with zeroes, like the hardware monitor situation above.


    Then, when writing from REU to RAM addresses $0000 and $0001, these two writes will be silently ignored, and the original values there will not be changed.


    I have attached a test program developed with llvm-mos:



    that contains source code (probably not that useful unless you have been dabbling at llvm-mos) + compiled ready-to-run .PRG (probably more useful for testing):


    reucpy.zip



    I don't know what the correct behavior of using REU to read/write from C64 addresses $0000 and $0001 should be, since I don't have a real REU - though here it looks clear that VICE and C64+TC2 behaviors diverge.


    In my use case, I was able to work around this behavioral difference by not using the REU to read or write to the CPU addresses $0000 and $0001, since they go ignored on TC2. After that, I see again my program works the same on real C64 as it does on VICE.

  • On a real machine, the REU will never be able to read the CPU DDR and IO port. It will always read/write the actual memory locations $0000 and $0001, which are unreachable for the 6510 CPU. On the other hand, the data direction register and IO port are not accessible from the "outside", and even writes to these locations are "invisible" on the external bus.


    You may know that you can read the actual memory locations with a "detour": Set VIC to Hires, bank 0, first half, then probe the first 16 bits with a single-pixel sprite and check collision. However, there is no way to access these memory locations for writing, unless you have an REU or some other DMA_capable cartridge.


    Jens

  • > The first divergence I see is that in Turbo Chameleon 2 Hardware Monitor, when one types "m 0", the monitor always displays 00 00 for the first two bytes of the address space, and not the actual CPU Processor Port Data Direction and Processor Port map register values.


    THat is by design. The chameleon monitor always shows RAM. The VICE monitor has different modes, by default it shows what the cpu "sees", if you use "bank ram" it will behave like the chameleon monitor.


    Interesting issue about the REU in VICE. Since making the REU in VICE as perfect as possible is one of my hobbies :) I will look at it right now :)

  • Awesome!


    That made me wonder whether there might be other addresses/address ranges that a REU should have no possibility to update (but that VICE might). The address ranges that I am saving to REU and then restoring are now ($0002 - $C7FF) and ($D000 - $DC03) inclusive. The upper D000 range contains a lot of data that I am not completely sure about (the idea is to clear C64 sprite, sound and other memory back to known cleared/disabled state). DC03 limit was a bit arbitrarily decided for now, saving/restoring up to DDFF might also be apt. (DE00 - DFFF wouldn't want to touch since it is already the I/O area and REU itself)


    I suppose something will manifest itself in the future if there is something that isn't good to access via REU that way.

  • (The 0/1 thing is fixed in VICE)


    You can transfer anywhere, and select the banking via $01 as needed. However, transfers from/to I/O can be glitchy - they usually work (and there are programs that rely on it), but it is not good practise, and occasionally you might get a broken transfer. Transfers to RAM under I/O (D000-DFFF) are always fine and no problem.