Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QNICE writes to manually-loadable ROMs on hard reset. #56

Open
Rhialto opened this issue Dec 7, 2024 · 4 comments
Open

QNICE writes to manually-loadable ROMs on hard reset. #56

Rhialto opened this issue Dec 7, 2024 · 4 comments
Assignees
Labels
question Further information is requested research

Comments

@Rhialto
Copy link

Rhialto commented Dec 7, 2024

Copied from discord https://discord.com/channels/719326990221574164/782759365064917065/1315000073444135034

The QNICE core, when starting up, seems to write to several of the "core specific devices" as listed in C_CRTROMS_MAN. I caught it doing that and enabling qnice_dev_we_i for several of them. The disk drive does a checksum of its ROMs and then fails. It shows that by doing 2 flashes of its drive led, repeatedly.
I though to maybe avoid it by changing the number of the drive ROM, but this made no difference. Now the changed number appears, and write is done to addrexx $3000 in its address space....
I had to disable writing to the drive ROM for now until I find out what's going on exactly.

Screenshot_2024-12-07_19-06-17

I found out where it happens. I suppose the QNICE code doesn't change often so my addresses are probably reproducable. It is at 24A1 in a function called CRTROM_CSR_W. It is called from 237D just below the label _CRTRI_L9 and the comment ; set all CSRs of all CRT/ROM devices to "idle".

008328                                                
008329                                                ; set all CSRs of all CRT/ROM devices to "idle"
008330  2373  0F80  81D4                              MOVE CRTROM_MAN_NUM, R0
008331  2375  0040                                    MOVE @R0, R0
008332  2376  0F84  81D8                              MOVE CRTROM_MAN_DEV, R1
008333  2378  0FA4  7000                              MOVE CRTROM_CSR_STATUS, R9
008334  237A  0FA8  0000                              MOVE CRTROM_CSR_ST_IDLE, R10
008335  237C  01A0        _CRTRI_L9                   MOVE @R1++, R8
008336  237D  FFB0  011A                              RSUB CRTROM_CSR_W, 1
008337  237F  3F80  0001                              SUB 1, R0
008338  2381  FFAB  FFF9                              RBRA _CRTRI_L9, !Z
...
008599                    ; Write to the control and status register of a CRT/ROM device
008600                    ; Input:                    
008601                    ; R8: device id             
008602                    ; R9: CSR register          
008603                    ; R10: value                
008604                    ; Output: none, all registers remain unchanged
008605  2499  E0C0        CRTROM_CSR_W                INCRB
008606                                                
008607  249A  0F80  FFF4                              MOVE M2M$RAMROM_DEV, R0
008608  249C  0801                                    MOVE R8, @R0
008609  249D  0F80  FFF5                              MOVE M2M$RAMROM_4KWIN, R0
008610  249F  0F81  FFFF                              MOVE CRTROM_CSR_4KWIN, @R0
008611  24A1  0A25                                    MOVE R10, @R9
008612                  
008613  24A2  E100                                    DECRB
008614  24A3  0DBC                                    MOVE @R13++, R15
@Rhialto
Copy link
Author

Rhialto commented Dec 7, 2024

I found out that when this happens, the full qnice_dev_addr is ffff000. That's the 4K window ffff which is mentioned as the "csr window".

I can use that to disable writing. I will try that next.

The drive ROM of course truncates the address to a smaller number of bits since it's of limited size.

I hope that the qnice core does actually store this csr-page data somewhere else, because there is no room for it in the various ROMs...

@Rhialto
Copy link
Author

Rhialto commented Dec 7, 2024

No, it doesn't...
after loading a ROM the QNICE cpu gets stuck in a loop here:

008769                                                ; wait until parsing is done and retrieve status
008770  2526  0020                                    MOVE R0, R8
008771  2527  0FA4  7010                              MOVE CRTROM_CSR_PARSEST, R9
008772  2529  FFB0  FF79  _HNDLCRTROM_1               RSUB CRTROM_CSR_R, 1
008773  252B  CFA8  0002                              CMP CRTROM_CSR_PT_OK, R10
008774  252D  FFA3  0006                              RBRA _HNDLCRTROM_2, Z
008775  252F  CFA8  0003                              CMP CRTROM_CSR_PT_ERR, R10
008776  2531  FFA3  000A                              RBRA _HNDLCRTROM_3, Z
008777  2533  FFA0  FFF4                              RBRA _HNDLCRTROM_1, 1

I think we need an extra device type, one for ROM-like things, that don't have a CSR.

Edit: from a quick look, it seems that

; R10: mode selector: 0=virtual drives 1=manually loadable CRTs/ROMs

already would do the right thing for R10=0, at least it seems like it would skip that loop at the end. But the value has other effects, so maybe it won't work.

@sy2002 sy2002 self-assigned this Dec 8, 2024
@sy2002
Copy link
Owner

sy2002 commented Dec 8, 2024

@Rhialto Thank you for raising this issue. I am currently very busy with life so I do not have a ton of time to support you and/or fix a bug, if there is one. Currently I guess there is no bug - but who knows :-)

To quickly check the basics:

  1. Can you please copy/paste the output that QNICE writes to the serial terminal into this issue for me having a look? If you did not work with the serial terminal, yet in the M2M context: Use your JTAG. Set your terminal software to 115,200 baud 8-N-1, no flow control such as XON/XOFF, RTS/CTS, DTR/DSR. (More details here: https://github.com/sy2002/MiSTer2MEGA65/wiki/3.-%22Hello-World%22-Tutorial#understanding-the-qnice-debug-console). The output on the serial terminal is normally pretty verbose and shows various details that might be helpful to double-check, if we have no "obvious errors".

  2. Can you please point me to some files in your GitHub repo where you are implementing the stuff

I am sorry, that this whole mechanism is currently not very well documented (not documented at all). So we need to do a bit of forensics together.

It is important that you implement the CSR protocol when working with the On-Screen-Menu to load ROMs or things like that. An example how to do it is shown in:

https://github.com/MJoergen/C64MEGA65/blob/master/CORE/vhdl/prg_loader.vhd

Look at lines 69++

The protocol helper is here:

https://github.com/sy2002/MiSTer2MEGA65/blob/master/M2M/vhdl/qnice_csr.vhd

And don't forget that QNICE operates on the falling edge. You need to support this CSR protocol and we suggest that you use qnice_csr.vhd for it.

Another example which uses qnice_csr.vhd is here: https://github.com/MJoergen/C64MEGA65/blob/master/CORE/vhdl/sw_cartridge_csr.vhd But this is way more complicated. The above-mentioned prg_load much more mimics the "data pump" that you might be looking for.

My guess is: You did not implement this protocol and this is why the QNICE firmware crashes.

Also another question to you: Can you clarify your use case? Do you want ROMs to be automatically loaded on startup? Then you need to use the auto-load mechanism, which is different from the manual loading mechanism described here. Auto = on startup / hard-reset and Manual = user uses the file browser to pick it. An example of the automatic mechanism is the Jiffy DOS loading mechanism as shown in the C64 core:

  1. In globals.vhd: https://github.com/MJoergen/C64MEGA65/blob/master/CORE/vhdl/globals.vhd#L177
  2. In mega65.vhd: https://github.com/MJoergen/C64MEGA65/blob/master/CORE/vhdl/mega65.vhd#L864C15-L864C37

But in this case, also the MiSTer code needs to be changed for accomodating the falling-edge nature of QNICE, example: https://github.com/MJoergen/C64_MiSTerMEGA65/blob/5afb90e02fcefb053ac27792f42e742ad61e8b9b/rtl/iec_drive/c1541_multi.sv#L111

It might also make sense to have a Skype call together, i.e. you, @MJoergen and I to get to know each other and to resolve this here quickly. Feel free to dm me on Discord.

@sy2002 sy2002 added question Further information is requested research labels Dec 8, 2024
@Rhialto
Copy link
Author

Rhialto commented Dec 8, 2024

Thanks for all the info, @sy2002 ! I see now that this is not a bug, but merely a difference in use case and/or expectations.

Let me explain how I got to the implementation that I did. It is at https://github.com/Rhialto/PET_MEGA65 and https://github.com/Rhialto/PET2001_MiSTer/ .

I started with the PET2001 core from MiSTer. Into that I copied the c1541 code from the C64MEGA65 core.

PETs have many different models and a big difference between those is in the ROM contents. There are many different version of the "editor" ROM E000-E7FF or -EFFF. Too many to count. Furthermore there are 2 or 3 empty sockets for 4 KB ROMs and there are many of those around. So having loadable ROMs is kind of essential.

Further I like to have at least one set pre-loaded so that you don't need to do much setup to use the core. No extra files on the SDcard needed. And as I understand it, auto-load ROMs aren't automatically loadable by hand anyway.

So the 1541 and also the PET came with an interface already to load the ROMs. Here is a fragment from the C64 core applying that to the 1541: https://github.com/MJoergen/C64MEGA65/blob/master/CORE/vhdl/mega65.vhd#L864

         -- Custom Kernal Access: C1541 ROM
         when C_DEV_C64_KERNAL_C1541 =>
            qnice_c1541rom_addr        <= "00" & qnice_dev_addr_i(13 downto 0);
            qnice_c1541rom_we          <= qnice_dev_we_i;
            qnice_dev_data_o           <= x"00" & qnice_c1541rom_data_from;
            qnice_c1541rom_data_to     <= qnice_dev_data_i(7 downto 0);

I used essentially the same for my copied drive.

The PET also had a similar access to the internals, https://github.com/MiSTer-devel/PET2001_MiSTer/blob/master/rtl/pet2001hw.sv#L66

	input  [15:0]    dma_addr, // 1 line added so to support 32KB RAM PRG Injection
	input   [7:0]    dma_din,
	output  [7:0]    dma_dout,
	input            dma_we,

Indeed for this I had to add the qnice clock, and rearrange the internal dual ported RAMs a bit.

So this is how I got to use the ROM loader. I just wired it up the same. The floppy disk buffers are also wired up the same.

I think that for something as simple as a plain ROM this qnice protocol is not needed. The examples I saw don't implement it. And I suspect that if a ROM load option for the 1541 was added to the menu of the C64MEGA65 core, it would fail in the same way as it did for me. I guess nobody got around to trying it out so far.

For now I worked around the issue by always returning OK (2) from a read on the CSR page, and ignoring writes to it. But it would be simpler if the qnice code treated a simple ROM load the same as a floppy disk mount. I noticed in the code that this case is tested in a few places, and there is a note somewhere that these don't have a CSR. Having that as a supported case for ROM loads sounds like a good solution to me. https://github.com/Rhialto/PET_MEGA65/blob/v0.00005/CORE/vhdl/mega65.vhd#L556

      qnice_csr_window           :=      '1' when qnice_dev_addr_i(27 downto 12) = x"FFFF"
                                    else '0';
...
         -- Custom Kernal Access: PET main ROMs
         when C_DEV_PET_KERNAL_PET =>
            qnice_petrom_addr          <= qnice_dev_addr_i(14 downto 0);
            qnice_petrom_we            <= qnice_dev_we_i and not qnice_csr_window;
            qnice_dev_data_o           <= CRTROM_CSR_PT_OK when qnice_csr_window else
                                          x"00" & qnice_petrom_data_from;
            qnice_petrom_data_to       <= qnice_dev_data_i(7 downto 0);
            qnice_petchars_ce          <= '0';

I could strip down prg_loader.vhd to a rom_loader.vhd but it would just pass through pretty much everything except csr data. It would not even need any state, really. It doesn't even remember the file name, if I see it right. So I don't see much value there, to be honest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested research
Projects
None yet
Development

No branches or pull requests

2 participants