Closed sy2002 closed 7 months ago
Using commit 7abc351 (from Oct 29): EoB works. This is just before the long-reset fix. Using commit f241136 (from Oct 30): EoB does not work. This is just after the long-reset fix.
To be continued ....
@MJoergen I probably will find time to debug this over the week-end; to avoid double-work, I am mentioning this here; you could un-assign yourself from this.
@MJoergen Here is what I found out so far and reminder: For the C64 to recognize and start a cartridge instead of going to BASIC, the signature CBM80
needs to be located from $8004..$8008, in PETSCII these are the values: C3 C2 CD 38 30
. The KERNAL routine which does this check, reads backwards, i.e. from $8008 to $8004. So what we would expect when loading a cartridge is that after the CRT loading is completed, at some moment, the cart_roml_n
signal goes low, indicating that the C64 reads in the cartridge area $8xxx.
And exactly this is what happens, when I load a "small" cartridge, for example Canabalt:
hard_reset_n = 0
active (follow link) that would use c64_ram_data <= x"00"
to mask the CBM80
(which is exactly what happens during a long/hard reset to ensure that the C64 "really and always reboots")And this is why Alienator, Canabalt or other "small" cartridges are starting correctly.
What I also found out:
Even when loading a "big" cartridge such as EoB: There is never any spurious long reset being generated anywhere outside of main.vhd and no spurious hard_reset_n
being generated inside main.vhd. The latter one would mask the "CBM80" signature as written above. So if the C64 core - also when loading a "big" cartridge such as EoB - wants to access the cartridge memory, it always can.
And here is the puzzle:
When loading a big cartridge, the C64 core is reset in a way or behaves in a way that it never ever generates any cart_roml_l signal at all: It seems not to run through the cold start init sequence.
Another (minor? or irrelevant?) thing I discovered:
I don't think that this has anything to do with the phenomenon but I will test it later:
Reminder: The agreed upon semantics (which is not documented anywhere, note-to-self to fix this soon): Within the main.vhd of the Commodore 64 core we are not using the reset signals that come from "outside", but stick to our internal, C64 core-specific, reset logic of hard and soft resets and what those "mean".
Technically this means: There are two reset signals generated in the hard_reset
process: reset_core_n
is a soft reset of the core and hard_reset_n
is a long reset of the core. All components in main.vhd
are adhering to this semantics but two are not: i_reu_mapper
and i_avm_cache
are using the outside-generated i_reset_soft
instead of the inside-generated reset_core_n
which means that these resets are out of sync.
The deeper I am diving, the more a start to be convinced that our old implementation in V5 only worked by chance and that fixing the long reset bug is uncovering deeper, more complex issues. Next puzzle piece is from fpga64_sid_iec.vhd
(MiSTer file):
process(clk32)
begin
if rising_edge(clk32) then
if preCycle = sysCycleDef'high then
reset <= not reset_n;
end if;
end if;
end process;
sysCycleDef
is a custom type used for the state machine and consists of 32 states that are cycled through, one per rising core clock. reset_n
is the input signal to the MiSTer core and reset
is a signal that the core internally uses.
This code basically tells us: If the incoming reset signal is too short, then bad things will happen. We never took this into consideration so far.
Great analysis!
i_reu_mapper
and i_avm_cache
are not adhering to the overall reset semantics seems wrong. I know who wrote that part, and I'm pretty sure he didn't consider this. I'm pretty sure they should both use the soft reset, i.e. reset_core_n
@MJoergen Thank you for your feedback. Here is the next finding:
1) Canabalt (which works), is a 16KB Cartridge and according to this documentation does what is expected: One clock cycle after reset_core_n
is de-asserted (goes back to 1
), we see both, exrom
and game
(both low-active, too) going to zero. This is what a so called "16 KB Cartridge" is supposed to do:
2) Eye of the Beholder (EoB), which does not work, is a complex cartridge with bank switching (I assume it is in EasyFlash Format but did not check that yet). exrom
and game
should do something - but they are not:
This is the reason, why - as described in the comment above (https://github.com/MJoergen/C64MEGA65/issues/108#issuecomment-1806798071) "behaves in a way that it never ever generates any cart_roml_l signal at all".
And without cart_roml_l
there is no way to read anything from the simulated cartridge.
And cart_rom_l
depends on either ultimax=1
or exrom = '0' and bankSwitch(1) = '1' and bankSwitch(0) = '1' and cpuWe = '0'
: See this code
Our situation: bankSwitch(1) and (0) are 1 because "7" = binary "111" and I also checked that cpuWe is zero in the situations when we have $8008 downto $8004 on the address bus
This leads to the conclusion that for some reason exrom and game are not set properly due to the new (bugfixed) reset beahavior.
In main.vhd we have:
-- Simulated cartridge using data from .crt file
when 2 =>
core_game_n <= crt_game;
core_exrom_n <= crt_exrom;
And crt_game
and crt_exrom
are outputs of i_cartridge
. So my next step is now to instrument i_cartridge
and see what happens there when EoB is loaded. Stay tuned - I'll keep you posted.
My God! This is a real cliff-hanger!!!
I'm eagerly and curiously waiting for the resolution of this bug. The suspense is driving me crazy!
@MJoergen And here is the resolution of the cliff-hanger:
When I fixed the long reset bug, I also changed the reset input for i_cartridge - see screenshot of commit. This was a mistake:
From hard-reset to soft-reset. This is the wrong semantics: The component sets the correct exrom_o and game_o while cart_loading_i='1'. During a reset signal via "rst_i" exrom_o, game_o and other stateful signals are reset to the neutral state. Due to the fact, that sw_cartridge_wrapper uses a soft reset to make sure the C64 starts the cartridge, we must not reset i_cartridge on soft reset.
The commit https://github.com/MJoergen/C64MEGA65/commit/17f06ab8869110869c66d906724d929388b1c408 fixes the issue and I also seized the opportunity to document the C64 core's (very core-specific) reset semantics in main.vhd.
Presumably introduced in Alpha 3, which is based on commit c099921 and from 11/02/23
Observation with Alpha 3 on an R3 board:
a) loading and running
.crt
files: Canabalt Encore and Alienator load and start like a charmeb) A bunch of tested hardware cartridges work like a charme (we might need to dig deeper, if all known HW carts still work)
c) Eye of the Beholder: Loads, then a black screen for a second or so, then a reset and then back to BASIC.
The main difference between Canabalt and Alienator are: They are "small" and EoB is "big" (well: very big).