maziac / DeZog

Visual Studio Code Debugger for Z80/ZX Spectrum.
MIT License
212 stars 35 forks source link

Zsim: load instruction not executed properly for addresses between 0x0000 and 0x3FFF #29

Closed Centurion256 closed 3 years ago

Centurion256 commented 3 years ago

Describe the bug If a load instruction to an address in the range of 0x0000 and 0x3FFF is executed, the data in that memory cell will not change. This will happen regardless of the "loadZxRom" option in launch.json. A similar problem is encountered if the stack pointer is set in this range.

To Reproduce

  1. Create a launch.json, select "zsim" as the preferred simulator, add a "loadObjs" parameter and set it to the corresponding binary file and a start address of "0x0000".
  2. Assemble (preferably with sjasmplus) a source file which contains the following code:
    
    ;...
    low_addr: equ 0x3FFF ;can be any value in range [0x0000, 0x3FFF]
    .db 00
    ;...
    ld hl, low_addr
    ld a, 0xFF ;can be any other value
    ld (hl), a

high_addr: equ 0x4000 ;can be any value >= 0x4000 .db 00 ;.... ld hl, high_addr ld a, 0xFF ;can be any other value ld (hl), a ;...

3. Run the program in debug mode and inspect the corresponding memory locations after the each set of instructions has been run. Only the higher address will actually be filled with 0xFF, the lower address will remain unchanged.

**Expected behavior**
Both memory locations ought to be filled with 0xFF.

**Screenshots**
I successfully reproduced this bug with unit tests
![Z80Err](https://user-images.githubusercontent.com/16632436/93709642-91c44e80-fb48-11ea-8a36-81b37b749545.png)
The following GIF illustrates the memory dump during the execution of `UT_ld_low_addrs`:
![Z80UnitErrLow](https://user-images.githubusercontent.com/16632436/93709843-6cd0db00-fb4a-11ea-9e75-41eb281fdbf2.gif)
For the `UT_ld_high_addrs` the memory behaviour is normal, i.e. no need to illustrate.
**Version etc. (please complete the following information):**
 - DeZog: 1.4.8 
 - OS: Solus Linux
 - Remote: zsim

**Additional context**
I mainly use dezog and zsim to develop and debug firmware code(BIOS) for my own custom made Z80 computer and not for ZX Spectrum or any of it's variants. As far as I know, there is no reason why such behavior should occur on native Z80 (I personally tested similar code on a physical Z80 CPU chip), but I'm unfamiliar with ZX Spectrum memory layout and limitations. Perhaps this is the intended behavior of zsim, in which case this issue is irrelevant.

I originally encountered this issue when working with a different configuration, but later switched to a unit test and the issue persists. Here is the unit test configuration:
```json
        {
            "type": "dezog",
            "request": "launch",
            "name": "Unit Tests",
            "unitTests": true,
            "remoteType": "zsim",
            "zsim": {
                "loadZxRom": false,
                "zxKeyboard": false,
                "visualMemory": false,
                "ulaScreen": false,
                "vsyncInterrupt": false,
                "cpuLoadInterruptRange": "0"
            },
            "resetOnLaunch": true,
            "skipInterrupt": true,
            "commandsAfterLaunch": [
                "-wpmem enable",
                "-assert enable",
                "-logpoint enable",
            ],
            "disassemblerArgs": {
                "esxdosRst": true
            },
            "listFiles": [
                {
                    "path": "unit_tests.lst",
                    "asm": "sjasmplus",
                    "mainFile": "unit_tests.asm"
                },
            ],
            "rootFolder": "${workspaceFolder}",
            "loadObjs": [
                {"path": "unit_tests.bin", "start": "0x0000"}
            ]
        }
maziac commented 3 years ago

Thanks for submitting this issue. I will have a look. I assume that it has something to do with the ZX spectrum configuration. zsim should be first a Z80 simulator with some extensions for ZX Spectrum. I.e. it should allow to load data also in 0x0000-0x3FFF area (which is ROM in ZX Spectrum) if "loadZxRom" is false.

BTW you are the first one I know of that really has taken the unit tests into use. Nice to see it in action for someone else.

maziac commented 3 years ago

Please try the fix here: https://github.com/maziac/DeZog/releases/tag/v1.4.9 and let me know if it helps.

Centurion256 commented 3 years ago

Yes, it indeed works now. Both unit tests pass. Thank you!

I'm curious, what was the cause of such weird behavior? Perhaps there was some implicit memory protection done by zsim? I'll have a look at the source code.

Regarding unit tests, I always prefer to ensure the correctness of my code, and it was very difficult and tedious to do so for Z80 Assembly, since I had to flash the ROM of my computer each time. I'm developing my custom Z80 Based computer with support for virtual memory and it's own custom BIOS/OS (You can check it out here if you're interested), and this means that assuring the validity of the source code before uploading it is crucial. I have a few other suggestions for this extension that would help improve the experience for native Z80, such as custom I/O, but I think I'll post that in a different thread. Again, thank you for addressing this issue.

maziac commented 3 years ago

The root cause was that "loadZxRom" only handled the loading of the ROM data. Even if not loaded, the area was still ROM. As it is for the Spectrum.

Seems you have an interesting project there.

If you have further suggestions please let me know.