bool CapriceOpenDisk::HandleMessage(CMessage* pMessage) { bool bHandled = false; if (pMessage) { switch(pMessage->MessageType()) { case CMessage::CTRL_SINGLELCLICK: { if (pMessage->Destination() == this) { if (pMessage->Source() == m_pButtonCancel) { CloseFrame(); CMessageServer::Instance().QueueMessage(new CMessage(CMessage::APP_EXIT, 0, this)); break; } if (pMessage->Source() == m_pButtonOpen) { // Put selected ROM filename on button: (if there is a selection) int selectedDiskIndex = m_pListBoxDisk->getFirstSelectedIndex(); if (selectedDiskIndex >= 0) { DriveFile = (m_pListBoxDisk->GetItem(selectedDiskIndex)).sItemText; if (selDrive) strncpy(CPC.drvB_file, DriveFile.c_str(), sizeof(CPC.drvB_file)); else strncpy(CPC.drvA_file, DriveFile.c_str(), sizeof(CPC.drvA_file)); std::string pchFile = DrivePath+DriveFile; dsk_load(pchFile.c_str(),pDrive,'A'); CloseFrame(); CMessageServer::Instance().QueueMessage(new CMessage(CMessage::APP_EXIT, 0, this)); } break; } if (pMessage->Source() == m_pButtonClear) { if (selDrive) { strcpy(CPC.drvB_file, ""); } else { strcpy(CPC.drvA_file, ""); } dsk_eject(pDrive); CloseFrame(); bHandled = true; break; } CMessageServer::Instance().QueueMessage(new CMessage(CMessage::APP_EXIT, 0, this)); } break; } default : bHandled = CFrame::HandleMessage(pMessage); break; } } return bHandled; }
int dsk_load (const std::string &filename, t_drive *drive) { int iRetCode = 0; LOG_DEBUG("Loading disk: " << filename); dsk_eject(drive); if ((pfileObject = fopen(filename.c_str(), "rb")) != nullptr) { iRetCode = dsk_load(pfileObject, drive); fclose(pfileObject); } else { LOG_ERROR("File not found: " << filename); iRetCode = ERR_FILE_NOT_FOUND; } if (iRetCode != 0) { // on error, 'eject' disk from drive dsk_eject(drive); } return iRetCode; }
int dsk_load (FILE *pfile, t_drive *drive) { LOG_DEBUG("Loading disk"); dword dwTrackSize, track, side, sector, dwSectorSize, dwSectors; byte *pbPtr, *pbDataPtr, *pbTempPtr, *pbTrackSizeTable; if(fread(pbGPBuffer, 0x100, 1, pfile) != 1) { // read DSK header LOG_ERROR("Couldn't read DSK header"); return ERR_DSK_INVALID; } pbPtr = pbGPBuffer; if (memcmp(pbPtr, "MV - CPC", 8) == 0) { // normal DSK image? LOG_DEBUG("Loading normal disk"); drive->tracks = *(pbPtr + 0x30); // grab number of tracks if (drive->tracks > DSK_TRACKMAX) { // compare against upper limit drive->tracks = DSK_TRACKMAX; // limit to maximum } drive->sides = *(pbPtr + 0x31); // grab number of sides if (drive->sides > DSK_SIDEMAX) { // abort if more than maximum LOG_ERROR("DSK header has " << drive->sides << " sides, expected " << DSK_SIDEMAX << " or less"); dsk_eject(drive); return ERR_DSK_SIDES; } dwTrackSize = (*(pbPtr + 0x32) + (*(pbPtr + 0x33) << 8)) - 0x100; // determine track size in bytes, minus track header drive->sides--; // zero base number of sides for (track = 0; track < drive->tracks; track++) { // loop for all tracks for (side = 0; side <= drive->sides; side++) { // loop for all sides if(fread(pbGPBuffer+0x100, 0x100, 1, pfile) != 1) { // read track header LOG_ERROR("Couldn't read DSK track header for track " << track << " side " << side); dsk_eject(drive); return ERR_DSK_INVALID; } pbPtr = pbGPBuffer + 0x100; if (memcmp(pbPtr, "Track-Info", 10) != 0) { // abort if ID does not match LOG_ERROR("Corrupted DSK track header for track " << track << " side " << side); dsk_eject(drive); return ERR_DSK_INVALID; } dwSectorSize = 0x80 << *(pbPtr + 0x14); // determine sector size in bytes dwSectors = *(pbPtr + 0x15); // grab number of sectors if (dwSectors > DSK_SECTORMAX) { // abort if sector count greater than maximum LOG_ERROR("DSK track with " << dwSectors << " sectors, expected " << DSK_SECTORMAX << "or less"); dsk_eject(drive); return ERR_DSK_SECTORS; } drive->track[track][side].sectors = dwSectors; // store sector count drive->track[track][side].size = dwTrackSize; // store track size drive->track[track][side].data = static_cast<byte *>(malloc(dwTrackSize)); // attempt to allocate the required memory if (drive->track[track][side].data == nullptr) { // abort if not enough LOG_ERROR("Couldn't allocate " << dwTrackSize << " bytes to store track " << track << " side " << side); dsk_eject(drive); return ERR_OUT_OF_MEMORY; } pbDataPtr = drive->track[track][side].data; // pointer to start of memory buffer pbTempPtr = pbDataPtr; // keep a pointer to the beginning of the buffer for the current track for (sector = 0; sector < dwSectors; sector++) { // loop for all sectors memcpy(drive->track[track][side].sector[sector].CHRN, (pbPtr + 0x18), 4); // copy CHRN memcpy(drive->track[track][side].sector[sector].flags, (pbPtr + 0x1c), 2); // copy ST1 & ST2 drive->track[track][side].sector[sector].setSizes(dwSectorSize, dwSectorSize); drive->track[track][side].sector[sector].setData(pbDataPtr); // store pointer to sector data pbDataPtr += dwSectorSize; pbPtr += 8; } if (dwTrackSize > 0 && !fread(pbTempPtr, dwTrackSize, 1, pfile)) { // read entire track data in one go LOG_ERROR("Couldn't read track data for track " << track << " side " << side); dsk_eject(drive); return ERR_DSK_INVALID; } } } drive->altered = 0; // disk is as yet unmodified } else { if (memcmp(pbPtr, "EXTENDED", 8) == 0) { // extended DSK image? LOG_DEBUG("Loading extended disk"); drive->tracks = *(pbPtr + 0x30); // number of tracks LOG_DEBUG("with " << drive->tracks << " tracks"); if (drive->tracks > DSK_TRACKMAX) { // limit to maximum possible drive->tracks = DSK_TRACKMAX; } drive->random_DEs = *(pbPtr + 0x31) & 0x80; // simulate random Data Errors? drive->sides = *(pbPtr + 0x31) & 3; // number of sides LOG_DEBUG("with " << drive->sides << " sides"); if (drive->sides > DSK_SIDEMAX) { // abort if more than maximum LOG_ERROR("DSK header has " << drive->sides << " sides, expected " << DSK_SIDEMAX << " or less"); dsk_eject(drive); return ERR_DSK_SIDES; } pbTrackSizeTable = pbPtr + 0x34; // pointer to track size table in DSK header drive->sides--; // zero base number of sides for (track = 0; track < drive->tracks; track++) { // loop for all tracks for (side = 0; side <= drive->sides; side++) { // loop for all sides dwTrackSize = (*pbTrackSizeTable++ << 8); // track size in bytes LOG_DEBUG("Track " << track << ", side " << side << ", size " << dwTrackSize); if (dwTrackSize != 0) { // only process if track contains data dwTrackSize -= 0x100; // compensate for track header if(fread(pbGPBuffer+0x100, 0x100, 1, pfile) != 1) { // read track header LOG_ERROR("Couldn't read DSK track header for track " << track << " side " << side); dsk_eject(drive); return ERR_DSK_INVALID; } pbPtr = pbGPBuffer + 0x100; if (memcmp(pbPtr, "Track-Info", 10) != 0) { // valid track header? LOG_ERROR("Corrupted DSK track header for track " << track << " side " << side); dsk_eject(drive); return ERR_DSK_INVALID; } dwSectors = *(pbPtr + 0x15); // number of sectors for this track LOG_DEBUG("with " << dwSectors << " sectors"); if (dwSectors > DSK_SECTORMAX) { // abort if sector count greater than maximum LOG_ERROR("DSK track with " << dwSectors << " sectors, expected " << DSK_SECTORMAX << "or less"); dsk_eject(drive); return ERR_DSK_SECTORS; } drive->track[track][side].sectors = dwSectors; // store sector count drive->track[track][side].size = dwTrackSize; // store track size drive->track[track][side].data = static_cast<byte *>(malloc(dwTrackSize)); // attempt to allocate the required memory if (drive->track[track][side].data == nullptr) { // abort if not enough LOG_ERROR("Couldn't allocate " << dwTrackSize << " bytes to store track " << track << " side " << side); dsk_eject(drive); return ERR_OUT_OF_MEMORY; } pbDataPtr = drive->track[track][side].data; // pointer to start of memory buffer pbTempPtr = pbDataPtr; // keep a pointer to the beginning of the buffer for the current track pbPtr += 0x18; for (sector = 0; sector < dwSectors; sector++) { // loop for all sectors memcpy(drive->track[track][side].sector[sector].CHRN, pbPtr, 4); // copy CHRN memcpy(drive->track[track][side].sector[sector].flags, (pbPtr + 0x04), 2); // copy ST1 & ST2 dword dwRealSize = 0x80 << *(pbPtr+0x03); dwSectorSize = *(pbPtr + 0x6) + (*(pbPtr + 0x7) << 8); // sector size in bytes drive->track[track][side].sector[sector].setSizes(dwRealSize, dwSectorSize); drive->track[track][side].sector[sector].setData(pbDataPtr); // store pointer to sector data pbDataPtr += dwSectorSize; pbPtr += 8; LOG_DEBUG("Sector " << sector << " size: " << dwSectorSize << " real size: " << dwRealSize << " CHRN: " << chrn_to_string(drive->track[track][side].sector[sector].CHRN)); } if (dwTrackSize > 0 && !fread(pbTempPtr, dwTrackSize, 1, pfile)) { // read entire track data in one go LOG_ERROR("Couldn't read track data for track " << track << " side " << side); dsk_eject(drive); return ERR_DSK_INVALID; } } else { LOG_DEBUG("empty track"); memset(&drive->track[track][side], 0, sizeof(t_track)); // track not formatted } } } drive->altered = 0; // disk is as yet unmodified } else { LOG_ERROR("Unknown DSK type"); dsk_eject(drive); return ERR_DSK_INVALID; // file could not be identified as a valid DSK } } return 0; }