Closed reidrac closed 5 years ago
OK, I think I may found something.
In CLK, if I check if 0xffff supports sslots... it doesn't support it. I skip that part and everything's fine. I think it shouldn't affect anything if I fiddle with 0xffff if there's no sslots; but I don't know.
Basically it can be detected like this:
ld a, (#0xffff)
cpl
ld b, a
ld (#0xffff), a
ld a, (#0xffff)
cp b
jp z, skip_sslot_setup
I don't know if this makes any sense.
No, none of the things in the primary slots in CLK implement a secondary slot register. I actually might need to revisit that even before I get into the whole issue of the MSX 2, as I think some of the European MSX 1s provide 128kb RAM via secondary slot paging, and that some tape games use that functionality. Typing this extemporaneously SWIV feels like it might be an example, but don't quote me on that.
Such that it's relevant, I'm still trying to formulate complete feelings about the MSX 2. I've never actually used one, and coming up with an efficient implementation of the VDP's command engine could be a hassle.
Independently of any future MSX 2 support, this may be red herring. Why the code stops working if I don't check for 0xffffff behaviour? Then I continued adding features when I thought that the check was a good workaround, and it stopped working again.
I don't know what is it, it may be an unrelated piece of code and I'm looking at the wrong place.
I'll look at it a bit more tonight.
I've just noticed that --quickload
is always on, even if you don't provide it on the command line.
Just on --quickload
, that's technically by design. Whether it's a good design, I don't know. When launching from the command line, the program takes the 'user-friendly' selection set for each machine and then patches it with anything the user has been explicit about. So --quickload=no
should work.
Quick update: I've been looking at this again and I changed my code to use the BIOS, with a similar result.
I also tried the old version an a real MSX and it works as expected.
I think I've come around to the conclusion that I should just implement secondary slot selection registers, even if there's no extra memory to select, as then I'm in the ballpark of very well-defined behaviour expectations. Also even just amongst MSX 1 titles it seems that some of the European game conversions expect to be able to use secondary slot selection in order to get access to 128kb.
Right now I'm deep in implementing the Master System, as a pretext for forcing greater generality into my TMS with an eye to the MSX 2. I'm hoping to be done with that, at least to first viable release standards, in a week or two. This is mentally scheduled for after that; it'll be a neat segue if I'm looking to keep momentum up on MSX improvements.
Thanks Tom. I'm quite confused, I'm new to the MSX and I still think there might be something wrong in my code.
I'm fairly confused too; the emulator doesn't currently do anything at all to distinguish $ffff
from any other memory address, in any of its slots.
If it helps as to a reader's guide, https://github.com/TomHarte/CLK/blob/master/Machines/MSX/MSX.cpp#L439 is where the MSX handles a Z80 write cycle*. So on 440 it stores the value somewhere. Then if there is a slot handler for the slot being written to, it also updates that slot's concept of time, and that of the audio stream, and communicates the write onward.
For RAM there's no slot handler. The disk ROM has one, cartridges with paging and/or audio hardware have one. It's just how the emulator hooks extra processing on when necessary, and it tries to avoid doing so because those are virtual function calls.
Right now slots that don't have RAM underneath them install a sink for the uninteresting writes, but I keep dithering on that as a strategy. It avoids a conditional, but increases memory usage. So probably the conditional is better.
* or, at least, the part of a write cycle that signals the actual write, which is only the second half. There's a separate bus operation for beginning of a write cycle, and one for wait during a write cycle supposing a wait were signalled. The rule is that each thing the processor communicates is an indivisible chunk. It samples the wait line halfway through the cycle and then may wait for an arbitrary period of time, so the whole action actually needs to be divided into two to make indivisible portions.
I've been reading that file, yes. The thing that confuses me is that it works in the real machine and openMSX emulating different machines, so CLK seems to be odd one out and it bothers me that I don't know what is it! (specially because I see some old games loading from CAS just fine)
I've changed the code to use the BIOS, with a similar result.
I appreciate your time on this issue, I just hope is not just me getting things wrong!
EDIT: if this helps, I use TAPION/TAPIOFF from the BIOS. Probably unrelated, or may be not. Can be something related to the cassette interface (?).
Well, I've finally spotted an issue in this area, albeit while sitting far from my development machine and just browsing the code from another desk. I establish whether I should use the fast-load hack based entirely on the state of the tape player:
use_fast_tape_ = !tape_player_is_sleeping_ && allow_fast_tape_ && tape_player_.has_tape();
Which, essentially means: motor is on && the user wants fast loading && there is a tape. I then check for whether to intercept TAPION and TAPIN with code like:
case CPU::Z80::PartialMachineCycle::ReadOpcode:
if(use_fast_tape_) {
if(address == 0x1a63) {
// TAPION
etc. With CPU::Z80::PartialMachineCycle::ReadOpcode
being the internal shorthand for "it's a read cycle in which M1 is active".
But, regardless, an obvious error there: I'm failing to check that the BIOS is paged. So is it possible that your code, or some part of it, runs over 0x1a63
and/or TAPIN at 0x1abc
? If so then per that bug the CPU will supply a 0xC9 (intended to be a RET, though if the byte being read with an M1 cycle isn't the first in an opcode, it'll end up being something else) that isn't actually in your code. And, best case, your routine will just terminate early.
Supposing you're just using a regular assembler, that also might explain why you've experienced a bit of a heisenbug: it's about which part of which routine happens to straddle those addresses.
It's a definite bug, so I'll definitely fix it, but is it possible it's the cause of this issue?
I have no idea. Since October last year I'm running an equivalent piece of code using the BIOS, hoping that it will be more portable (it is at least easier to read).
I'm using a regular assembler, but I'm not currently where I can read my code. I'll take a quick look tonight and I'll try to answer your questions. Thanks!
This is the code I'm using at the moment that works with openMSX (and my PAL MSX) but doesn't with CLK:
di
ld sp, #0xf380
ei
call RSLREG
rrca
rrca
and #3
ld c, a
add a, #0xc1
ld l, a
ld h, #0xfc
ld a, (hl)
and #0x80
or c
ld c, a
inc l
inc l
inc l
inc l
ld a, (hl)
and #0x0c
or c
ld h, #0x80
call ENASLT
It is using the BIOS and I can't see what can be wrong here!
There's also the fact that seems to randomly fail or work depending on apparently irrelevant changes.
EDIT: probably unrelated but trying to load CAS with code in master results in the wrong aspect ratio or rendering problems. That doesn't happen with cart.
Oh, re: aspect ratio, that's because for the sake of acknowledging the difference at all, I temporarily decided that tapes are primarily European software, so you get a 50Hz PAL machine. Which, naturally, has a different aspect ratio. I dare imagine I'll walk back from that.
I'll fix the fast tape trap code either this evening or during the course of the weekend; it would certainly fit with failures resulting from irrelevant changes but we'll see. If you have the time to spare, you could try loading with quickload=false and see whether that makes a difference.
It doesn't look like it makes any difference. The BIOS I'm using is NTSC though (using a PAL BIOS doesn't make any difference).
Oh well. I've probably discovered an unrelated issue then — it fits the profile for being only triggerable from tapes and being likely to change in effect if your code changes, but I nevertheless think is distinct. Ho hum.
If you were willing to supply a CAS then that might help with debugging, on the off-chance it's some other memory map issue that I won't easily be able to recreate without happening to get your example code placed at exactly the right address, but if it's not easy to sever the broken part then don't worry about it.
I'll fix the other thing, and keep hunting!
The game will be released in April :)
I can share with you a private copy of the beta if that helps.
Having had a quick inspection of the beta, I actually think the issue is my CAS handling — the bit of code that reads a CAS and turns it into a wave. Nothing within the actual emulation side of things. So the actual final issue with the CAS exactly as received is that it branches into a TAPION when there are ostensibly no remaining files no the cassette. But what I've actually done is chop up the CAS into files incorrectly.
Per MSX CAS Packager, the first off-the-shelf tool I found to investigate these things, the tape contains:
ascii | nightk | 256 bytes | bin | loader | 558 bytes | [0xe000,0xe227]:0xe000 custom | | 529 bytes | custom | | 17747 bytes |
Per my CAS code, it contains a 16-byte file, loader is just an 18850-byte length file. So it looks like I've swallowed one of the intended file headers (as 18850 = 17747+529+16, and headers are 16-bytes long) into the loader file.
One of the conditions I was led to believe applied to CAS files by https://www.msx.org/forum/semi-msx-talk/emulation/how-do-exactly-works-cas-format was that files always begin on an 8-byte boundary. I think that might be misinformation. But it would be another cause of slight changes in code leading to unexpected changes in behaviour.
So I'll work on my CAS parsing.
The sample CAS that you sent me now loads and plays correctly, as do the various other CASs that I've tested. So I didn't actually mean for #595 to close this issue, but it quite possibly does. Let me know.
I think this can explain the issues I was describing here.
Unfortunately I pulled from master and tested it to get a segfault. Currently it can't load ROMs either.
That's embarrassing; I'm out right now but will endeavour to reproduce and fix this evening. If it's both tapes and cartridges then almost certainly I've made an error with the new tape motor LED — it's the responsibility of whomever owns an LED not to message to null if there's presently no target for LED updates, so I guess I've made a mistake there, and not fully tested the SDL startup sequence. Probably an initialised variable or something of that ilk.
On 2 Mar 2019, at 15:30, Juan J. Martínez notifications@github.com wrote:
I think this can explain the issues I was describing here.
Unfortunately I pulled from master and tested it to get a segfault. Currently it can't load ROMs either.
— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub, or mute the thread.
No worries! Thanks Tom.
It’s likely this issue is now fixed.
On 2 Mar 2019, at 15:44, Juan J. Martínez notifications@github.com wrote:
No worries! Thanks Tom.
— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/TomHarte/CLK/issues/546#issuecomment-468958339, or mute the thread https://github.com/notifications/unsubscribe-auth/ABG7qNvyAWk6wm8o-lhbPfHGi0jPrgPAks5vSuKWgaJpZM4WgwTu.
It is indeed! Thanks!
This is perhaps a question more than a bug report.
I'm trying to setup the memory after loading from CAS:
This is the code I'm using (that could be wrong):
This seems to work with MSX1 and MSX2 on OpenMSX, but in CLK I can't make it work. I didn't have problems setting the memory when booting from cartridge, so I'm assuming that CLK uses a different slot configuration.
Any pointers would be appreciated!
(I tried reading MSX.cpp, but I couldn't get anything clear enough)