|
From: Maarten t. H. <ma...@tr...> - 2003-03-30 04:36:03
|
On Monday 24 March 2003 21:24, Wouter Vermaelen wrote: > > So I think the > > only solution is to remove all reset() calls from constructors and call > > reset() externally after construction. > > > > This also creates a clear separation of concerns: the constructor's > > purpose is to allocate objects, reset's purpose is to initialise the > > state of the emulated hardware. I even think it is possible to remove the > > EmuTime parameter from the constructor. This makes it impossible for the > > constructor to do I/O with other subsystems, since all I/O requires a > > timestamp, thereby avoiding initialisation bugs like I'm trying to fix > > now in the VDP. > > Initializing and resetting may not always be exactly the same. Therefor I > suggest to create a new powerOn() method and call this method instead of > reset(). The default implementation for powerOn() can just call reset(). I don't think it's a good idea to have powerOn() call reset(): - it might lead to the same problems as the constructor calling reset() - on real hardware, there is an actual reset pulse shortly after power up, so the most straightforward way to emulate this, is to call reset() after powerOn() - if we ever want to support insertion / removal of extensions at run time, those devices are powered up but do not receive a reset signal: powerOn() should called but not reset() - for example MegaROM mappers are not in their usual initial state if you insert them when the MSX is active That said, having a powerOn() method in addition to the constructor and reset() would make sense, because it allows us to emulate everything the hardware does. For example VRAM has a fixed initial state (checkerboard or single colour, depending on hardware), but is not reinitialised on a reset. The responsibilities would be: - constructor: emulation-specific bookkeeping (such as object allocation) - powerOn(): initialise state to power-up values - reset(): reinitialise state the way hardware does on reset The powerOn() and reset() methods would get a timestamp parameter (EmuTime), the constructor would not. The call sequence is like this: - all devices are constructed - all devices are powered up - all devices are reset It can be very difficult to know the power up state of a device, since it is not documented and impossible to measure for built-in devices (without hardware modifications). It is possible the power up state is partly random. It might depend on implementation details that are usually invisible to the outside world. For most devices, approximating power up behaviour by performing a reset is good enough. But it should not call the reset() method, instead the reset-initialisation code should be in a private method which is invoked from both powerOn() and reset(). Some things to discuss: Should we implement powerOn() now or at a later time? The only use I see is emulation of inserting a cartridge into a running machine, which is something that will probably require additional architectural changes. So I think it's safe to postpone the implementation. Is "powerOn()" or "powerUp()" a better name? I have a slight preference for the latter, because a device powers up when the user turns the power on (does this make sense to people other than me?). > > I'll implement separate construction and reset in the VDP first, since > > it's a self-contained piece of code. If it works well, we could use it > > for all devices in openMSX. > > If it would help your VDP work, we can now already create and call the > powerOn() method. This means most devices will get reset()ed twice for > a while, but I don't think it's that bad (not even if some device > don't get fixed before 0.2.2). It is not necessary to change MSXDevice because all changes are inside the VDP. However, as VDP subsystems have some behaviour (but no classes) in common with devices, they can act as a tryout area for these changes. Bye, Maarten |