Closed mithrendal closed 4 years ago
loaded with the new introduced html5 file dialog
Very cool. Seems like out current lock down is a booster for retro development π€€.
but nothing special happens ...
API calls look fine as far as I can tell π€. In case of a CRT, you need to reset the computer after attaching. Did you do that? To test the D64 case, we need to be able to type something useful inside the emulator, e.g., "LOAD "$",8
In case of a CRT, you need to reset the computer after attaching. Did you do that?
Oh yes, that did the trick !!
else if (checkFileSuffix(name, ".CRT")|| checkFileSuffix(name, ".crt")) {
printf("isCRT\n");
wrapper->c64->expansionport.attachCartridge( Cartridge::makeWithCRTFile(wrapper->c64,(CRTFile::makeWithBuffer(blob, len))));
wrapper->c64->reset();
}
seeing it here with a loaded crt file ...
BTW: of course Rambo is sitting in the heli ...
for the floppies I have setup an keyboard interface first and for commanding the heli I need a game controller interface ...
The pieces are all there in vC64 !!! Fitting them together is like going on a easter egg hunt in the garden... Every new working piece means an massive explosion of dopamin directly into rambos brain cellsπ€€π€€π€€...
seeing it here with a loaded crt file ...
Woohoo, Fort Apocalypse inside a cartridge inside a C64 inside a browser. Kind of a digital version of Russian Matrjoschkas π.
BTW: of course Rambo is sitting in the heli ...
Hmmm, not sure... wait... zooming in π§... coming closer... uhhhhh .... indeed π³:
I better not distract him too much. The blue heli usually appears from nowhere π¬.
The pieces are all there in vC64
If the puzzle gets too complicated, use me as a Siri interface. Like a Siri for API questions π€.
to be able to better view and understand the log output π (it does scroll every 3 seconds) I decided to disable the c64 property takeAutoSnapshots ... but unfortunately it was declared as private π±...
mainsdl.cpp:470:10: error: 'takeAutoSnapshots' is a private member of 'C64'
c64->takeAutoSnapshots=false;
^
C64/C64.h:246:10: note: declared private here
bool takeAutoSnapshots = true;
^
1 error generated.
I want to keep the C64 core as unpatched as possible ... but I just did it again π©
#ifdef __EMSCRIPTEN__
public:
#else
private:
#endif
//! @brief Indicates if snapshots should be taken automatically.
bool takeAutoSnapshots = true;
I am very careful with the precious c64 core emulator, therefore all patches applied to the files in the folder C64 can be easily found by searching for the keyword EMSCRIPTEN
but unfortunately it was declared as private π±
That's an easy one π.
Use C64::setTakeAutoSnapshots(false)
//
//! @functiongroup Handling snapshots
//
public:
//! @brief Indicates if the auto-snapshot feature is enabled.
bool getTakeAutoSnapshots() { return takeAutoSnapshots; }
//! @brief Enables or disabled the auto-snapshot feature.
void setTakeAutoSnapshots(bool enable) { takeAutoSnapshots = enable; }
/*! @brief Disables the auto-snapshot feature temporarily.
* @details This method is called when the snaphshot browser opens.
*/
void suspendAutoSnapshots() { autoSnapshotInterval -= (LONG_MAX / 2); }
/*! @brief Heal a call to suspendAutoSnapshots()
* @details This method is called when the snaphshot browser closes.
*/
void resumeAutoSnapshots() { autoSnapshotInterval += (LONG_MAX / 2); }
//! @brief Returns the time between two auto-snapshots in seconds.
long getSnapshotInterval() { return autoSnapshotInterval; }
//! @brief Sets the time between two auto-snapshots in seconds.
void setSnapshotInterval(long value) { autoSnapshotInterval = value; }
/*! @brief Loads the current state from a snapshot file
* @note There is an thread-unsafe and thread-safe version of this
* function. The first one can be unsed inside the emulator
* thread or from outside if the emulator is halted. The second
* one can be called any time.
*/
void loadFromSnapshotUnsafe(Snapshot *snapshot);
void loadFromSnapshotSafe(Snapshot *snapshot);
Had to rebase and roll that already pushed commit back. π± In which I made that guy public
Shame on me that I did not saw the setter methods. π¬
"Walk of Atonement" ... π€ ... googling ... oh, Games of Thrones π―
I never watches that series, because I usually have problems following movies and series with too many characters π. I do love clean and simple concepts, and Games of Thrones seems to be the opposite (at least this is what I've heard).
Yesterday, I watched "Doom - The Movie" on Netflix which really has a clean a simple concept. The movie can be summarized easily: A gate to hell opens. Marines enter the gate.
Very clean and simple concept π. To be honest, it was much better than I thought.
I am at the point where I have to do the keyboard... there are different approaches ...
case SDL_KEYUP:
...
case SDLK_r:
c64->keyboard.releaseKey(2, 1); //r;
break;
...
2. do everything in javascript and just hand over the correct keycodes to a exported C method which then just presses what javascript wants...
something like this
javascript part
c64_key = Module.cwrap('js_key', 'undefined', ['string', 'number']);
function keydown(e) { //alert('keydown'+e.code); c64_key(e.code, 1); } function keyup(e) { //alert('keyup'+e.code); c64_key(e.code, 0); }
document.addEventListener('keyup', keyup);
document.addEventListener('keydown', keydown);
C part in mainsdl
extern "C" void js_key(char* keyCode, int pressed) { if(pressed==1) { wrapper->c64->keyboard.pressKey( ...); } else { wrapper->c64->keyboard.releaseKey(... ); } }
in 1. we could do all the event handling in mainsdl, which is simple but very closed to others...
I like 2. approach much more because it is open and flexible .... others could reuse the WASM binaries without the need of recompiling and add cool onscreen keyboards done in fancy HTML
In my opinion we should strictly head to way2 and give javascript as much control as possible. we have already loadFile(CRT,D64...) ... as there is to come: keyboard, game controller, toggleFullscreen, getSnapshot, loadSnapshot, reset, ...
Keeping the event handling of WASM part only to an absolute minimum of very specific SDL related events ...
In my opinion we should strictly head to way2 and give javascript as much control as possible.
Yes, I think that's the way to go. From the two major factors to consider here (speed and flexibility), speed is not an issue. Thus, I would also go for the more flexible approach.
Furthermore, we might want to have a virtual keyboard later π. Such a keyboard would have to interact with the JavaScript part, too, I guess.
BTW, do you have some oversight w.r.t. web GUI frameworks? Function wise, I think we should have something similar to SAE eventually. But maybe with a fancier look and feel (with animated controls, cool overlay effects, whatever is possible in modern HTML).
fancy webGUI, yes I want to have some responsive design here πͺπΎ π. Responsive Design, because it should look also good on a mobile device. Maybe some bootstrap, jquery .... we will do that later !
BTW: I just tested on an iPhone6s with a connected bluetooth keyboard. Way2: It accepts the keys typed on the keyboard and directly passes them via javascript into the wasm part. Also Fullscreen button worked ... but screen ratio was a bit weird π... the well known effect of a fat robin hood in landscape and way to thin robin in portrait mode....
I just tested on an iPhone6s with a connected bluetooth keyboard
Wow, great progress. Sounds like you are on hyper-drive. I'm still fighting with vAmigas new snapshot / screenshot browser π€.
Sounds like you are on hyper-drive.
no not really π, familiy π¨βπ©βπ§βπ¦ is asking for more social time with dad ... in the time between I just picking some low hanging fruits here and there. The path is clear now, I think it will slowly but steadily converge to an interesting thing...
Yes, I think that's the way to go. From the two major factors to consider here (speed and flexibility), speed is not an issue. Thus, I would also go for the more flexible approach.
Yep, for me now it has become competely clear that we must keep the C side wrapper in mainsdl.cpp as simple as possible without any additional logic and in the same time as open as possible to javascript.... All logic has to be done in the javascript part. That way the compiled WASM binary can be adapted to various browser environments, future browser changes .. without changing the C side part ...
I will prefix the C methods which are exported to Javascript with "wasm_" prefix ... with that way, on the C side, we know that the guy is for javascript. And on the javascript side, we know that it is the guy on the WASM side...
like this ...
javascript side...
//init c wrappers
wasm_loadfile = Module.cwrap('wasm_loadFile', 'undefined', ['string', 'array', 'number']);
wasm_key = Module.cwrap('wasm_key', 'undefined', ['string', 'number']);
wasm_toggleFullscreen = Module.cwrap('wasm_toggleFullscreen', 'undefined');
....
//call c wrapper, for example load a file
wasm_loadfile(file.name, byteArray, byteArray.byteLength);
C side
extern "C" void wasm_loadFile(char* name, Uint8 *blob, long len)
{
...
I will make many of these π until the Emulator is completely controllable from the javascript side.
keyboard works so far π ... all done in javascript ... ok most keys ...enough to type Load"$",8,1 oder Load"*",8,1
Lets try to insert a disk ...
constructing C64 ...
adding a listener to C64 message queue...
vC64 message=MSG_PAL, data=0
vC64 message=MSG_VC1541_ATTACHED_SOUND, data=1
vC64 message=MSG_VC1541_ATTACHED, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_MOTOR_OFF, data=1
vC64 message=MSG_VC1541_NO_DISK, data=1
vC64 message=MSG_DISK_SAVED, data=1
vC64 message=MSG_PAL, data=0
vC64 message=MSG_NO_CARTRIDGE, data=0
vC64 message=MSG_CART_SWITCH, data=0
vC64 message=MSG_IEC_BUS_IDLE, data=0
vC64 message=MSG_VC1541_ATTACHED, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_MOTOR_OFF, data=1
vC64 message=MSG_VC1541_NO_DISK, data=1
vC64 message=MSG_DISK_SAVED, data=1
vC64 message=MSG_VC1541_DETACHED, data=2
vC64 message=MSG_VC1541_RED_LED_OFF, data=2
vC64 message=MSG_VC1541_MOTOR_OFF, data=2
vC64 message=MSG_VC1541_NO_DISK, data=2
vC64 message=MSG_DISK_SAVED, data=2
vC64 message=MSG_VC1530_NO_TAPE, data=0
vC64 message=MSG_VC1530_PROGRESS, data=0
vC64 message=MSG_WARP_OFF, data=0
vC64 message=MSG_ALWAYS_WARP_OFF, data=0
set SID to freq= 44100
Mouse entered window 1
Window 1 gained keyboard focus
Window 1 shown
Window 1 hidden
Window 1 gained keyboard focus
Window 1 shown
Window 1 size changed to 428x284
Size changed: 428, 284
wrapper calls 4x c64->loadRom(...) method
vC64 message=MSG_READY_TO_RUN, data=0
wrapper calls run on c64->run() method
vC64 message=MSG_RUN, data=0
vC64 message=MSG_IEC_BUS_BUSY, data=0
Window 1 lost keyboard focus
vC64 message=MSG_IEC_BUS_IDLE, data=0
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_MOTOR_ON, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_MOTOR_OFF, data=1
vC64 message=MSG_IEC_BUS_BUSY, data=0
vC64 message=MSG_IEC_BUS_IDLE, data=0
load file=Blue_Max_[Synapse_1983].g64 len=333744
isG64
Assertion failed: insertionStatus == PARTIALLY_INSERTED, at: C64/Drive/Drive.cpp,483,insertDisk
uupps πwhen I insert a disk an assertion comes up ...
what am I missing ?
maybe
else if (checkFileSuffix(name, ".G64") || checkFileSuffix(name, ".g64")) {
printf("isG64\n");
wrapper->c64->drive1.insertDisk(G64File::makeWithBuffer(blob, len));
}
is not sufficient ? It complains PARTIALLY_INSERTED .... Do I have to close the drive door per API call ? π§
or maybe do some VC1541::prepareToInsert() voodooo dance ?
familiy is asking for more social time with dad ... in the time between I just picking some low hanging fruits here and there
I see, a classical text-book example of a time constraint. Here, Iβm faced with space constraints. My wife says I am turning our house into a museum π―. But hey, itβs just 5 Amiga 500s, a C64, and an Atari 2600. And the C64 is not even an original C64. It's a C64 Maxi manufactured in 2019. Therefore it can never count a museum item π.
or maybe do some VC1541::prepareToInsert() voodooo dance ?
Exactly. Emulating a C64 is brutal in the sense that many games rely on tiny aspects seen in real-life. As a result, even disk changes have to be emulated accurately. When a disk is inserted into the 1541 in real-life, the write-protection sensor gets blocked, independent of the protection status of the disk. Only when the disk got fully in (which requires a certain delay), the sensor gets unblocked for protected disks. To mimic this with VirtualC64, you need to do something similar to what the GUI does here:
if disk != nil {
drive.prepareToInsert()
usleep(300000)
drive.insertDisk(disk as? AnyArchiveProxy)
}
prepareToInsert
is a simple function that blocks the write-protection sensor. In addition, it sets the drive disk status to PARTIALLY_INSERTED to crash the emulator in insertDisk()
if somebody skips the preparation step π.
void
VC1541::prepareToInsert()
{
c64->resume();
debug("prepareToInsert\n");
assert(insertionStatus == NOT_INSERTED);
// Block the light barrier by taking the disk half out
insertionStatus = PARTIALLY_INSERTED;
c64->resume();
}
After calling this function, you are entitled to call insertDisk(β¦)
. The GUI code waits 0.3 sec between the calls which seems to work pretty well.
π€ Just spotted a bug in the code above. I am calling resume() twice π². The code is supposed to look like this:
void
VC1541::prepareToInsert()
{
suspend();
debug("prepareToInsert\n");
assert(insertionStatus == NOT_INSERTED);
// Block the light barrier by taking the disk half out
insertionStatus = PARTIALLY_INSERTED;
resume();
}
I guess I have to this Games of Thrones walk now. No? π¬
ok lets applying the latest patches to the core (the double resume horror thing) ...
and
patching the wrapper code with the prepare thing...
it now looks like this
if (checkFileSuffix(name, ".G64") || checkFileSuffix(name, ".g64")) {
printf("isG64\n");
wrapper->c64->drive1.prepareToInsert();
usleep(300000);
wrapper->c64->drive1.insertDisk(G64File::makeWithBuffer(blob, len));
printf("wasm_loadFile: disk inserted\n");
}
π€ Today is patch day
and lets insert the disk and hopefully the cores complaint about the partial insertion is gone ....
...
load file=Blue_Max_[Synapse_1983].g64 len=333744
isG64
vC64 message=MSG_VC1541_DISK, data=1
vC64 message=MSG_DISK_SAVED, data=1
vC64 message=MSG_VC1541_DISK_SOUND, data=1
wasm_loadFile: disk inserted
wasm_key ( 5, 2, 1 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 5, 2, 0 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 1, 7, 1 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 4, 6, 1 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 4, 6, 0 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 7, 3, 1 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 7, 3, 0 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 1, 7, 0 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 1, 7, 1 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 1, 3, 1 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 1, 3, 0 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 7, 3, 1 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 7, 3, 0 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 1, 7, 0 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 5, 7, 1 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 5, 7, 0 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 3, 3, 1 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 3, 3, 0 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 5, 7, 1 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 5, 7, 0 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 7, 0, 1 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 7, 0, 0 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 0, 1, 1 )
vC64 message=MSG_KEYMATRIX, data=0
wasm_key ( 0, 1, 0 )
vC64 message=MSG_KEYMATRIX, data=0
vC64 message=MSG_IEC_BUS_BUSY, data=0
vC64 message=MSG_VC1541_MOTOR_ON, data=1
vC64 message=MSG_VC1541_HEAD_UP, data=1
vC64 message=MSG_VC1541_HEAD_UP_SOUND, data=1
vC64 message=MSG_IEC_BUS_IDLE, data=0
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_UP, data=1
vC64 message=MSG_VC1541_HEAD_UP_SOUND, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_HEAD_DOWN_SOUND, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_UP, data=1
vC64 message=MSG_VC1541_HEAD_UP_SOUND, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_HEAD_DOWN_SOUND, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_HEAD_DOWN_SOUND, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_UP, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_UP, data=1
vC64 message=MSG_VC1541_HEAD_UP_SOUND, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_HEAD_DOWN_SOUND, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_IEC_BUS_BUSY, data=0
vC64 message=MSG_IEC_BUS_IDLE, data=0
Yes !! Strike back. It is really gone ! π
lets load the directory listing and see whats in there ...
ok lets load ...
lets llloooooaaaadddd
it loads really reeeeaaallllyyy slllloooowwww.
BTW: he is my favourite actor in this film https://www.youtube.com/watch?v=LZqvEcR_lDg
it does load forever .... π
Your webcam is on again π€.
BTW: he is my favourite actor in this film
Oups, sorry, I thought it was the webcam π.
it does load forever .... π
This is strange. The messages show that the drive head is moving. At the end, the IEC bus goes idle which means that there is no more bus activity (no more data transfer between the VC1541 and the C64). Did you check the D64 in the original VirtualC64? π€
Your webcam is on again π€.
yes true. Again.
Oups, sorry, I thought it was the webcam π.
indeed it was π³... the actor in my favourite film is my brother ...
Did you check the D64 in the original VirtualC64? π€
yes it loads
LOAD"$",8
searching for $
loading
ready
also other disks are stuck on searching for $ ....
do we have to debug ?? Patch the drive with some log output ?? Can you give me a hint where ? In case you like to have a look yourself ... I will push the current thing to the dev branch ...
do we have to debug ??
There are two major bug sources I could think of. 1) There might be some issue with the D64 file. 2) There might be an issue with the drive itself.
For 2), I think it's best to get some log output from the IEC bus. One of the main functions is this one:
void
IEC::updateIecLines()
{
bool signals_changed;
// Update bus lines
signals_changed = _updateIecLines();
if (signals_changed) {
c64->cia2.updatePA();
// ATN signal is connected to CA1 pin of VIA 1
c64->drive1.via1.CA1action(!atnLine);
c64->drive2.via1.CA1action(!atnLine);
if (tracingEnabled()) {
dumpTrace();
}
....
As you can seen, there is already some tracing support included. To start tracing the IEC bus, you can invoke method
void startTracing(int counter = -1) { traceCounter = counter; }
on the object to be traced. To enable it, add
iec->startTracing(1000); // Generates 1000 lines of trace output
to the constructor of the C64 class (C64::C64()
)
The trace output could then be compared to the original VirtualC64 output (with tracing enabled).
In the meantime, I can try to add some checksum support to VirtualC64 (back ported from vAmiga). This would tell us if the D64 data is OK.
There is a new brach in the VirtualC64 repo called βchecksumβ. The revision in this branch produces some important debug output for us. If a D64 file is inserted, two checksums are written to the console. One checksum is computed out of the D64 file data and the other one out of the GCR encoded data. E.g., my version of agents.d64 produces:
...
D64Archive: readFromBuffer: checksum = 5b8c08e0f4c3b181
...
Drive1: insertDisk: checksum = 890168ff800908d7
...
If those checksums are different in VirtualC64 and VirtualC64web, weβll know that there is some issue with the D64 files. This should be checked first.
To use the checksum feature in other code places, simply call this (global) function from anywhere in the code:
uint64_t fnv_1a_64(const uint8_t *addr, size_t size);
vc64web with checksum patch
vc64 checksum from branch
DragAndDrop.50::draggingEntered(_:): Dragged in filename
WindowDelegate.161::adjustWindowSize()
MyDocument.71::createAttachment(from:): Creating attachment from URL Blue_Max_[Synapse_1983].g64.
MyDocument.97::createAttachment(from:ofType:): Read 333744 bytes from file Blue_Max_[Synapse_1983].g64.
G64Archive: readFromBuffer: checksum = c73d1582c2971e92
MyDocument.194::mountAttachment(action:text:): Action = openBrowser
UserDialogController.16::showSheet(completionHandler:)
Animation.142::rotateBack(): Rotating back...
Drive1: prepareToInsert
Drive1: insertDisk
Drive1: insertDisk: checksum = 96c6da0a709de43c
Hmm, both checksums match. Actually, that's bad news, because this will be a nightmare to debug. Right now, I have no idea what could go wrong. π¬
Can you try to load the directory with LOAD "$",8
, omitting the ,1
?
yes I already tried that... load"$",8 without ,1 ... the same also no error in the logs it just becomes idle and stops ...
Files are ok because CRT and and PRGs work fine ... It must be something drive specific maybe timing related ? You know I had to replace the mach_time function with this guy. So the question is does the drive depend on timing ?
/* emulation of macos mach_absolute_time() function. */
long mach_absolute_time()
{
auto xnow = std::chrono::system_clock::now();
auto now_ns = std::chrono::time_point_cast<std::chrono::nanoseconds>(xnow);
auto epoch = now_ns.time_since_epoch();
auto now_ns_long = std::chrono::duration_cast<std::chrono::nanoseconds>(epoch).count();
return now_ns_long;
}
What happens if you type LOAD "$",8
without a disk present. Do you get the FILE NOT FOUND
error message or does it freeze again?
LOAD "$",8 SEARCHING FOR $
and it logs endless LED On/off messages ...
no file not found error message ... nor device not present message ...
So the question is does the drive depend on timing ?
No, the mach_absolute_time()
stuff only controls the speed of the emulator. The drive runs synchronously with the C64.
It could be some configuration issue. Maybe the original VirtualC64 is running in PAL mode and VirtualC64web in NTSC mode, or maybe some other config items differ. Every component has a dumpState()
method. This could be used to compare the macOS version with the web version. π€
definitely manufactured for EU market ... π
Maybe I've got an idea. In original VirtualC64, the emulator is running in a separate thread. When the GUI wants to interact with it, it
But in VirtualC64web, the suspend / resume mechanism is no longer there. This means that inserting a disk happens while the emulator is running which is likely to create an inconsistent state. Does this make sense so far? If yes, we need to find a way to halt emulation before we modify the emulator state from outside (from outside = from the GUI).
I also photographed this ... feeling like a paparazzi .. π¬
If yes, we need to find a way to halt emulation before we modify the emulator state from outside (from outside = from the GUI).
I understand the idea, but we also get misbehaviour when we are not modifying any state ... by simply typing LOAD"$",8 with no disk it reads endless, that is not normal ... and we did not alter the emulation state or did we ?
Does this make sense so far?
Answering this myself: It doesn't make sense. It wouldn't explain the behavior with no disk present πͺ.
great minds think a like
So we know something is wrong with the drive, even without a disk inserted ... I think we have to test it ... with log statements
I will try to add iec->startTracing(1000); // Generates 1000 lines of trace output at the end of the constructor right after reset()??
I checked how the drive messages normally look like when reading a directory. For some arbitrary D64, I got this in original VirtualC64:
MyController.737::processMessage(_:): MSG_IEC_BUS_BUSY
MyController.754::processMessage(_:): MSG_VC1541_MOTOR_ON
MyController.760::processMessage(_:): MSG_VC1541_HEAD_UP
MyController.748::processMessage(_:): MSG_IEC_BUS_IDLE
MyController.763::processMessage(_:): MSG_VC1541_HEAD_DOWN
MyController.763::processMessage(_:): MSG_VC1541_HEAD_DOWN
MyController.763::processMessage(_:): MSG_VC1541_HEAD_DOWN
MyController.763::processMessage(_:): MSG_VC1541_HEAD_DOWN
MyController.763::processMessage(_:): MSG_VC1541_HEAD_DOWN
MyController.763::processMessage(_:): MSG_VC1541_HEAD_DOWN
MyController.711::processMessage(_:): MSG_VC1541_RED_LED_ON
MyController.737::processMessage(_:): MSG_IEC_BUS_BUSY
MyController.724::processMessage(_:): MSG_VC1541_RED_LED_OFF
MyController.748::processMessage(_:): MSG_IEC_BUS_IDLE
The red drive led is switched on / off exactly once. In your log output, the red drive led blinks.
I see a lot of these ....
...
IEC: ATN: 1 CLK: 1 DATA: 1 vC64.html:1:528
IEC: ATN: 1 CLK: 0 DATA: 1 vC64.html:1:528
IEC: ATN: 1 CLK: 0 DATA: 0 vC64.html:1:528
IEC: ATN: 1 CLK: 1 DATA: 0 vC64.html:1:528
IEC: ATN: 1 CLK: 0 DATA: 1 vC64.html:1:528
IEC: ATN: 1 CLK: 0 DATA: 0 vC64.html:1:528
IEC: ATN: 1 CLK: 1 DATA: 0 vC64.html:1:528
IEC: ATN: 1 CLK: 0 DATA: 1 vC64.html:1:528
IEC: ATN: 1 CLK: 1 DATA: 1 vC64.html:1:528
IEC: ATN: 1 CLK: 0 DATA: 1 vC64.html:1:528
IEC: ATN: 1 CLK: 0 DATA: 0 vC64.html:1:528
IEC: ATN: 1 CLK: 1 DATA: 0 vC64.html:1:528
IEC: ATN: 1 CLK: 0 DATA: 1 vC64.html:1:528
IEC: ATN: 1 CLK: 0 DATA: 0 vC64.html:1:528
IEC: ATN: 1 CLK: 1 DATA: 0 vC64.html:1:528
IEC: ATN: 1 CLK: 0 DATA: 1
...
mine is here directly after load"$",8 with inserted disk
vC64 message=MSG_VC1541_MOTOR_ON, data=1
vC64 message=MSG_VC1541_HEAD_UP, data=1
vC64 message=MSG_VC1541_HEAD_UP_SOUND, data=1
vC64 message=MSG_IEC_BUS_IDLE, data=0
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_UP, data=1
vC64 message=MSG_VC1541_HEAD_UP_SOUND, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_HEAD_DOWN_SOUND, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_UP, data=1
vC64 message=MSG_VC1541_HEAD_UP_SOUND, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_HEAD_DOWN_SOUND, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_HEAD_DOWN_SOUND, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_UP, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_UP, data=1
vC64 message=MSG_VC1541_HEAD_UP_SOUND, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_VC1541_HEAD_DOWN, data=1
vC64 message=MSG_VC1541_HEAD_DOWN_SOUND, data=1
vC64 message=MSG_VC1541_RED_LED_OFF, data=1
vC64 message=MSG_VC1541_RED_LED_ON, data=1
vC64 message=MSG_IEC_BUS_BUSY, data=0
vC64 message=MSG_IEC_BUS_IDLE, data=0
right after the load"$",8 the original vc64 has a lot of MSG_VC1541_HEAD_DOWN where the webedition LED blinks on/off ...
Maybe a message from commodore ? They wan't to tell us something ... I bet they want to say us that the drive is broken ...
You are using the same drive Rom in VirtualC64 and VirtualC64web, aren't you? I'm running out of ideas π¬.
Can you push the current code to the repo?
You are using the same drive Rom in VirtualC64 and VirtualC64web, aren't you?
yes, I suppose to
just pushed to dev branch
but be careful ... on examining to core, maybe it is out of control already and can explode ... nucleaire chain reaction ??? β οΈ You will see the debug output in the browsers javascript web console.
Can you push the current code to the repo?
OK, downloaded...
Is it possible to see the native VirtualC64 debug messages somewhere? π€
You will see the debug output in the browsers javascript web console. Every browser has this nowadays something like "menu->extra->webdeveloper -> Javascript Console or Web console"
to load a file just click on the gray drop zone .... or drag a file into the drop zone...
OK, I can see the debug messages now.
I have found the problem ... I just took out the aggressive compiler optimization level3 out... with no optimisation at all the drive loads normally
let me guess first
Oh sorry I was too late updating the post
now lets see whether it hopefully works with -O2 or -O1 ?!!
I just took out the aggressive compiler optimization level3 out...
π€ Wow. I should run VirtualC64 with Xcode's sanitizer then. Compiler makers often make use of "undefined behavior" and many C/C++ programmers have such bugs in their code.
I learned that the hard way with a strange bug in Moira π.
OK, running Sanitizer to see how VirtualC64 is performing... π€€
Arghhh, lots of Sanitizer errors in reSID π. OK, I'm throwing reSID out temporarily...
Uhh, that sounds creepy: VirtualC64 has Shadow bytes π¬. Sounds like a disease π·.
2020-04-05 18:41:51.379392+0200 VirtualC64[58492:2650510] SUMMARY: AddressSanitizer: heap-buffer-overflow TimeDelayed.cpp:72 in TimeDelayed<unsigned char>::writeWithDelay(unsigned char, unsigned char)
2020-04-05 18:41:51.379434+0200 VirtualC64[58492:2650510] Shadow bytes around the buggy address:
2020-04-05 18:41:51.379471+0200 VirtualC64[58492:2650510] 0x1c0400008dd0: fa fa fd fa fa fa fd fa fa fa 00 fa fa fa fd fa
The good: Sanitizer has revealed a HUGE memory overflow bug in VirtualC64. I've fixed that on the main branch. The bad: Although Sanitizer doesn't complain any more when running VirtualC64mac, VirtualC64web still freezes with the old optimization level.
octopus in red π loaded with the new introduced html5 file dialog
loading individual PRG files is fine, but the other types like CRT files and so on are not working yet, maybe I did something wrong in the code below ? I just guessed from the virtualC64 API names what could be appropriate and called that guys but nothing special happens ...