Merge pull request #142 from AlexMartinelle/master
Experimental Pi Zero 1541 loading support.
This commit is contained in:
commit
65f982d07d
23 changed files with 833 additions and 73 deletions
|
@ -13,7 +13,7 @@ LD = $(PREFIX)ld
|
||||||
AR = $(PREFIX)ar
|
AR = $(PREFIX)ar
|
||||||
|
|
||||||
ifeq ($(strip $(RASPPI)),0)
|
ifeq ($(strip $(RASPPI)),0)
|
||||||
ARCH ?= -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -DRPIZERO=1
|
ARCH ?= -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -DRPIZERO=1 -DEXPERIMENTALZERO=1
|
||||||
CFLAGS += -DRPIZERO=1 -DRASPPI=1
|
CFLAGS += -DRPIZERO=1 -DRASPPI=1
|
||||||
else ifeq ($(strip $(RASPPI)),1)
|
else ifeq ($(strip $(RASPPI)),1)
|
||||||
ARCH ?= -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -DRPIBPLUS=1
|
ARCH ?= -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -DRPIBPLUS=1
|
||||||
|
|
|
@ -44,6 +44,7 @@ bool DiskCaddy::Empty()
|
||||||
if (disks[index].IsDirty())
|
if (disks[index].IsDirty())
|
||||||
{
|
{
|
||||||
anyDirty = true;
|
anyDirty = true;
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
if (screen)
|
if (screen)
|
||||||
{
|
{
|
||||||
x = screen->ScaleX(screenPosXCaddySelections);
|
x = screen->ScaleX(screenPosXCaddySelections);
|
||||||
|
@ -52,7 +53,7 @@ bool DiskCaddy::Empty()
|
||||||
snprintf(buffer, 256, "Saving %s\r\n", disks[index].GetName());
|
snprintf(buffer, 256, "Saving %s\r\n", disks[index].GetName());
|
||||||
screen->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red);
|
screen->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (screenLCD)
|
if (screenLCD)
|
||||||
{
|
{
|
||||||
RGBA BkColour = RGBA(0, 0, 0, 0xFF);
|
RGBA BkColour = RGBA(0, 0, 0, 0xFF);
|
||||||
|
@ -73,6 +74,7 @@ bool DiskCaddy::Empty()
|
||||||
|
|
||||||
if (anyDirty)
|
if (anyDirty)
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
if (screen)
|
if (screen)
|
||||||
{
|
{
|
||||||
x = screen->ScaleX(screenPosXCaddySelections);
|
x = screen->ScaleX(screenPosXCaddySelections);
|
||||||
|
@ -81,7 +83,7 @@ bool DiskCaddy::Empty()
|
||||||
snprintf(buffer, 256, "Saving Complete \r\n");
|
snprintf(buffer, 256, "Saving Complete \r\n");
|
||||||
screen->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red);
|
screen->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (screenLCD)
|
if (screenLCD)
|
||||||
{
|
{
|
||||||
RGBA BkColour = RGBA(0, 0, 0, 0xFF);
|
RGBA BkColour = RGBA(0, 0, 0, 0xFF);
|
||||||
|
@ -112,6 +114,7 @@ bool DiskCaddy::Insert(const FILINFO* fileInfo, bool readOnly)
|
||||||
FRESULT res = f_open(&fp, fileInfo->fname, FA_READ);
|
FRESULT res = f_open(&fp, fileInfo->fname, FA_READ);
|
||||||
if (res == FR_OK)
|
if (res == FR_OK)
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
if (screen)
|
if (screen)
|
||||||
{
|
{
|
||||||
x = screen->ScaleX(screenPosXCaddySelections);
|
x = screen->ScaleX(screenPosXCaddySelections);
|
||||||
|
@ -120,6 +123,7 @@ bool DiskCaddy::Insert(const FILINFO* fileInfo, bool readOnly)
|
||||||
snprintf(buffer, 256, "Loading %s\r\n", fileInfo->fname);
|
snprintf(buffer, 256, "Loading %s\r\n", fileInfo->fname);
|
||||||
screen->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red);
|
screen->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (screenLCD)
|
if (screenLCD)
|
||||||
{
|
{
|
||||||
|
@ -135,7 +139,6 @@ bool DiskCaddy::Insert(const FILINFO* fileInfo, bool readOnly)
|
||||||
screenLCD->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red);
|
screenLCD->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red);
|
||||||
screenLCD->SwapBuffers();
|
screenLCD->SwapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 bytesRead;
|
u32 bytesRead;
|
||||||
SetACTLed(true);
|
SetACTLed(true);
|
||||||
f_read(&fp, DiskImage::readBuffer, READBUFFER_SIZE, &bytesRead);
|
f_read(&fp, DiskImage::readBuffer, READBUFFER_SIZE, &bytesRead);
|
||||||
|
@ -254,6 +257,7 @@ void DiskCaddy::Display()
|
||||||
unsigned caddyIndex;
|
unsigned caddyIndex;
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
if (screen)
|
if (screen)
|
||||||
{
|
{
|
||||||
x = screen->ScaleX(screenPosXCaddySelections);
|
x = screen->ScaleX(screenPosXCaddySelections);
|
||||||
|
@ -281,6 +285,7 @@ void DiskCaddy::Display()
|
||||||
// RGBA BkColour = RGBA(0, 0, 0, 0xFF);
|
// RGBA BkColour = RGBA(0, 0, 0, 0xFF);
|
||||||
// screenLCD->Clear(BkColour);
|
// screenLCD->Clear(BkColour);
|
||||||
//}
|
//}
|
||||||
|
#endif
|
||||||
ShowSelectedImage(0);
|
ShowSelectedImage(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,6 +293,7 @@ void DiskCaddy::ShowSelectedImage(u32 index)
|
||||||
{
|
{
|
||||||
u32 x;
|
u32 x;
|
||||||
u32 y;
|
u32 y;
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
if (screen)
|
if (screen)
|
||||||
{
|
{
|
||||||
x = screen->ScaleX(screenPosXCaddySelections) - 16;
|
x = screen->ScaleX(screenPosXCaddySelections) - 16;
|
||||||
|
@ -295,6 +301,8 @@ void DiskCaddy::ShowSelectedImage(u32 index)
|
||||||
snprintf(buffer, 256, "*");
|
snprintf(buffer, 256, "*");
|
||||||
screen->PrintText(false, x, y, buffer, white, red);
|
screen->PrintText(false, x, y, buffer, white, red);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (screenLCD)
|
if (screenLCD)
|
||||||
{
|
{
|
||||||
unsigned numberOfImages = GetNumberOfImages();
|
unsigned numberOfImages = GetNumberOfImages();
|
||||||
|
@ -352,21 +360,23 @@ bool DiskCaddy::Update()
|
||||||
u32 caddyIndex = GetSelectedIndex();
|
u32 caddyIndex = GetSelectedIndex();
|
||||||
if (caddyIndex != oldCaddyIndex)
|
if (caddyIndex != oldCaddyIndex)
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
if (screen)
|
if (screen)
|
||||||
{
|
{
|
||||||
x = screen->ScaleX(screenPosXCaddySelections) - 16;
|
x = screen->ScaleX(screenPosXCaddySelections) - 16;
|
||||||
y = screen->ScaleY(screenPosYCaddySelections) + 16 + 16 * oldCaddyIndex;
|
y = screen->ScaleY(screenPosYCaddySelections) + 16 + 16 * oldCaddyIndex;
|
||||||
snprintf(buffer, 256, " ");
|
snprintf(buffer, 256, " ");
|
||||||
screen->PrintText(false, x, y, buffer, red, red);
|
screen->PrintText(false, x, y, buffer, red, red);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
oldCaddyIndex = caddyIndex;
|
oldCaddyIndex = caddyIndex;
|
||||||
ShowSelectedImage(oldCaddyIndex);
|
ShowSelectedImage(oldCaddyIndex);
|
||||||
}
|
|
||||||
|
|
||||||
if (screenLCD)
|
if (screenLCD)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -28,12 +28,19 @@ class DiskCaddy
|
||||||
public:
|
public:
|
||||||
DiskCaddy()
|
DiskCaddy()
|
||||||
: selectedIndex(0)
|
: selectedIndex(0)
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
, screen(0)
|
, screen(0)
|
||||||
|
#endif
|
||||||
, screenLCD(0)
|
, screenLCD(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
void SetScreen(Screen* screen, ScreenBase* screenLCD)
|
||||||
void SetScreen(Screen* screen, ScreenBase* screenLCD) { this->screen = screen; this->screenLCD = screenLCD; }
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
|
this->screen = screen;
|
||||||
|
#endif
|
||||||
|
this->screenLCD = screenLCD;
|
||||||
|
}
|
||||||
|
|
||||||
bool Empty();
|
bool Empty();
|
||||||
|
|
||||||
|
@ -41,6 +48,9 @@ public:
|
||||||
|
|
||||||
DiskImage* GetCurrentDisk()
|
DiskImage* GetCurrentDisk()
|
||||||
{
|
{
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
Update();
|
||||||
|
#endif
|
||||||
if (selectedIndex < disks.size())
|
if (selectedIndex < disks.size())
|
||||||
return &disks[selectedIndex];
|
return &disks[selectedIndex];
|
||||||
|
|
||||||
|
@ -50,14 +60,17 @@ public:
|
||||||
DiskImage* NextDisk()
|
DiskImage* NextDisk()
|
||||||
{
|
{
|
||||||
selectedIndex = (selectedIndex + 1) % (u32)disks.size();
|
selectedIndex = (selectedIndex + 1) % (u32)disks.size();
|
||||||
|
auto ret = GetCurrentDisk();
|
||||||
return GetCurrentDisk();
|
return GetCurrentDisk();
|
||||||
}
|
}
|
||||||
|
|
||||||
DiskImage* PrevDisk()
|
DiskImage* PrevDisk()
|
||||||
{
|
{
|
||||||
|
if (selectedIndex == 0u)
|
||||||
|
selectedIndex += (u32)disks.size()-1;
|
||||||
|
else
|
||||||
--selectedIndex;
|
--selectedIndex;
|
||||||
if ((int)selectedIndex < 0)
|
|
||||||
selectedIndex += (u32)disks.size();
|
|
||||||
return GetCurrentDisk();
|
return GetCurrentDisk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,8 +112,9 @@ private:
|
||||||
std::vector<DiskImage> disks;
|
std::vector<DiskImage> disks;
|
||||||
u32 selectedIndex;
|
u32 selectedIndex;
|
||||||
u32 oldCaddyIndex;
|
u32 oldCaddyIndex;
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
ScreenBase* screen;
|
ScreenBase* screen;
|
||||||
|
#endif
|
||||||
ScreenBase* screenLCD;
|
ScreenBase* screenLCD;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,12 @@ void DiskImage::Close()
|
||||||
|
|
||||||
void DiskImage::DumpTrack(unsigned track)
|
void DiskImage::DumpTrack(unsigned track)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
unsigned char* src = &tracks[track << 13];
|
||||||
|
#else
|
||||||
unsigned char* src = tracks[track];
|
unsigned char* src = tracks[track];
|
||||||
|
#endif
|
||||||
unsigned trackLength = trackLengths[track];
|
unsigned trackLength = trackLengths[track];
|
||||||
DEBUG_LOG("track = %d trackLength = %d\r\n", track, trackLength);
|
DEBUG_LOG("track = %d trackLength = %d\r\n", track, trackLength);
|
||||||
for (unsigned index = 0; index < trackLength; ++index)
|
for (unsigned index = 0; index < trackLength; ++index)
|
||||||
|
@ -205,7 +210,11 @@ bool DiskImage::OpenD64(const FILINFO* fileInfo, unsigned char* diskImage, unsig
|
||||||
for (unsigned halfTrackIndex = 0; halfTrackIndex < last_track * 2; ++halfTrackIndex)
|
for (unsigned halfTrackIndex = 0; halfTrackIndex < last_track * 2; ++halfTrackIndex)
|
||||||
{
|
{
|
||||||
unsigned char track = (halfTrackIndex >> 1);
|
unsigned char track = (halfTrackIndex >> 1);
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
unsigned char* dest = &tracks[halfTrackIndex << 13];
|
||||||
|
#else
|
||||||
unsigned char* dest = tracks[halfTrackIndex];
|
unsigned char* dest = tracks[halfTrackIndex];
|
||||||
|
#endif
|
||||||
|
|
||||||
trackLengths[halfTrackIndex] = SectorsPerTrack[track] * GCR_SECTOR_LENGTH;
|
trackLengths[halfTrackIndex] = SectorsPerTrack[track] * GCR_SECTOR_LENGTH;
|
||||||
|
|
||||||
|
@ -800,7 +809,11 @@ bool DiskImage::OpenG64(const FILINFO* fileInfo, unsigned char* diskImage, unsig
|
||||||
//DEBUG_LOG("trackLength = %d offset = %d\r\n", trackLength, offset);
|
//DEBUG_LOG("trackLength = %d offset = %d\r\n", trackLength, offset);
|
||||||
trackData += 2;
|
trackData += 2;
|
||||||
trackLengths[track] = trackLength;
|
trackLengths[track] = trackLength;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
memcpy(&tracks[track << 13], trackData, trackLength);
|
||||||
|
#else
|
||||||
memcpy(tracks[track], trackData, trackLength);
|
memcpy(tracks[track], trackData, trackLength);
|
||||||
|
#endif
|
||||||
trackUsed[track] = true;
|
trackUsed[track] = true;
|
||||||
//DEBUG_LOG("%d has data\r\n", track);
|
//DEBUG_LOG("%d has data\r\n", track);
|
||||||
}
|
}
|
||||||
|
@ -899,7 +912,11 @@ bool DiskImage::WriteG64(char* name)
|
||||||
|
|
||||||
gcr_track[0] = (BYTE)(track_len % 256);
|
gcr_track[0] = (BYTE)(track_len % 256);
|
||||||
gcr_track[1] = (BYTE)(track_len / 256);
|
gcr_track[1] = (BYTE)(track_len / 256);
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
memcpy(buffer, &tracks[track << 13], track_len);
|
||||||
|
#else
|
||||||
memcpy(buffer, tracks[track], track_len);
|
memcpy(buffer, tracks[track], track_len);
|
||||||
|
#endif
|
||||||
|
|
||||||
memcpy(gcr_track + 2, buffer, track_len);
|
memcpy(gcr_track + 2, buffer, track_len);
|
||||||
bytesToWrite = G64_TRACK_MAXLEN + 2;
|
bytesToWrite = G64_TRACK_MAXLEN + 2;
|
||||||
|
@ -965,11 +982,19 @@ bool DiskImage::OpenNIB(const FILINFO* fileInfo, unsigned char* diskImage, unsig
|
||||||
|
|
||||||
unsigned char* nibdata = diskImage + (t_index * NIB_TRACK_LENGTH) + 0x100;
|
unsigned char* nibdata = diskImage + (t_index * NIB_TRACK_LENGTH) + 0x100;
|
||||||
int align;
|
int align;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
trackLengths[track] = extract_GCR_track(&tracks[track << 13], nibdata, &align
|
||||||
|
//, ALIGN_GAP
|
||||||
|
, ALIGN_NONE
|
||||||
|
, capacity_min[trackDensity[track]],
|
||||||
|
capacity_max[trackDensity[track]]);
|
||||||
|
#else
|
||||||
trackLengths[track] = extract_GCR_track(tracks[track], nibdata, &align
|
trackLengths[track] = extract_GCR_track(tracks[track], nibdata, &align
|
||||||
//, ALIGN_GAP
|
//, ALIGN_GAP
|
||||||
, ALIGN_NONE
|
, ALIGN_NONE
|
||||||
, capacity_min[trackDensity[track]],
|
, capacity_min[trackDensity[track]],
|
||||||
capacity_max[trackDensity[track]]);
|
capacity_max[trackDensity[track]]);
|
||||||
|
#endif
|
||||||
|
|
||||||
trackUsed[track] = true;
|
trackUsed[track] = true;
|
||||||
|
|
||||||
|
@ -1031,7 +1056,11 @@ bool DiskImage::WriteNIB()
|
||||||
{
|
{
|
||||||
if (trackUsed[track])
|
if (trackUsed[track])
|
||||||
{
|
{
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
if (f_write(&fp, &tracks[track << 13], bytesToWrite, &bytesWritten) != FR_OK || bytesToWrite != bytesWritten)
|
||||||
|
#else
|
||||||
if (f_write(&fp, tracks[track], bytesToWrite, &bytesWritten) != FR_OK || bytesToWrite != bytesWritten)
|
if (f_write(&fp, tracks[track], bytesToWrite, &bytesWritten) != FR_OK || bytesToWrite != bytesWritten)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
DEBUG_LOG("Cannot write track data.\r\n");
|
DEBUG_LOG("Cannot write track data.\r\n");
|
||||||
}
|
}
|
||||||
|
@ -1250,10 +1279,18 @@ void DiskImage::DecodeBlock(unsigned track, int bitIndex, unsigned char* buf, in
|
||||||
unsigned char gcr[5];
|
unsigned char gcr[5];
|
||||||
unsigned char byte;
|
unsigned char byte;
|
||||||
unsigned char* offset;
|
unsigned char* offset;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
unsigned char* end = &tracks[track << 13] + trackLengths[track];
|
||||||
|
#else
|
||||||
unsigned char* end = tracks[track] + trackLengths[track];
|
unsigned char* end = tracks[track] + trackLengths[track];
|
||||||
|
#endif
|
||||||
|
|
||||||
shift = bitIndex & 7;
|
shift = bitIndex & 7;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
offset = &tracks[track << 13] + (bitIndex >> 3);
|
||||||
|
#else
|
||||||
offset = tracks[track] + (bitIndex >> 3);
|
offset = tracks[track] + (bitIndex >> 3);
|
||||||
|
#endif
|
||||||
|
|
||||||
byte = offset[0] << shift;
|
byte = offset[0] << shift;
|
||||||
for (i = 0; i < num; i++, buf += 4)
|
for (i = 0; i < num; i++, buf += 4)
|
||||||
|
@ -1262,7 +1299,11 @@ void DiskImage::DecodeBlock(unsigned track, int bitIndex, unsigned char* buf, in
|
||||||
{
|
{
|
||||||
offset++;
|
offset++;
|
||||||
if (offset >= end)
|
if (offset >= end)
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
offset = &tracks[track << 13];
|
||||||
|
#else
|
||||||
offset = tracks[track];
|
offset = tracks[track];
|
||||||
|
#endif
|
||||||
|
|
||||||
if (shift)
|
if (shift)
|
||||||
{
|
{
|
||||||
|
@ -1282,7 +1323,11 @@ void DiskImage::DecodeBlock(unsigned track, int bitIndex, unsigned char* buf, in
|
||||||
int DiskImage::FindSync(unsigned track, int bitIndex, int maxBits, int* syncStartIndex)
|
int DiskImage::FindSync(unsigned track, int bitIndex, int maxBits, int* syncStartIndex)
|
||||||
{
|
{
|
||||||
int readShiftRegister = 0;
|
int readShiftRegister = 0;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
unsigned char byte = tracks[(track << 13) + (bitIndex >> 3)] << (bitIndex & 7);
|
||||||
|
#else
|
||||||
unsigned char byte = tracks[track][bitIndex >> 3] << (bitIndex & 7);
|
unsigned char byte = tracks[track][bitIndex >> 3] << (bitIndex & 7);
|
||||||
|
#endif
|
||||||
bool prevBitZero = true;
|
bool prevBitZero = true;
|
||||||
|
|
||||||
while (maxBits--)
|
while (maxBits--)
|
||||||
|
@ -1314,7 +1359,11 @@ int DiskImage::FindSync(unsigned track, int bitIndex, int maxBits, int* syncStar
|
||||||
bitIndex++;
|
bitIndex++;
|
||||||
if (bitIndex >= MAX_TRACK_LENGTH * 8)
|
if (bitIndex >= MAX_TRACK_LENGTH * 8)
|
||||||
bitIndex = 0;
|
bitIndex = 0;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
byte = tracks[(track << 13)+(bitIndex >> 3)];
|
||||||
|
#else
|
||||||
byte = tracks[track][bitIndex >> 3];
|
byte = tracks[track][bitIndex >> 3];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -78,19 +78,48 @@ public:
|
||||||
|
|
||||||
bool GetDecodedSector(u32 track, u32 sector, u8* buffer);
|
bool GetDecodedSector(u32 track, u32 sector, u8* buffer);
|
||||||
|
|
||||||
|
inline unsigned char GetNextByte(u32 track, u32 byte)
|
||||||
|
{
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
return tracks[(track << 13) + byte];
|
||||||
|
#else
|
||||||
|
return tracks[track][byte];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool GetNextBit(u32 track, u32 byte, u32 bit)
|
inline bool GetNextBit(u32 track, u32 byte, u32 bit)
|
||||||
{
|
{
|
||||||
//if (attachedImageSize == 0)
|
//if (attachedImageSize == 0)
|
||||||
// return 0;
|
// return 0;
|
||||||
|
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
return ((tracks[(track << 13) + byte] >> bit) & 1) != 0;
|
||||||
|
#else
|
||||||
return ((tracks[track][byte] >> bit) & 1) != 0;
|
return ((tracks[track][byte] >> bit) & 1) != 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void SetBit(u32 track, u32 byte, u32 bit, bool value)
|
inline void SetBit(u32 track, u32 byte, u32 bit, bool value)
|
||||||
{
|
{
|
||||||
if (attachedImageSize == 0)
|
if (attachedImageSize == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
u8 dataOld = tracks[(track << 13) + byte];
|
||||||
|
u8 bitMask = 1 << bit;
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
TestDirty(track, (dataOld & bitMask) == 0);
|
||||||
|
tracks[(track << 13) + byte] |= bitMask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TestDirty(track, (dataOld & bitMask) != 0);
|
||||||
|
tracks[(track << 13) + byte] &= bitMask;
|
||||||
|
}
|
||||||
|
#else
|
||||||
u8 dataOld = tracks[track][byte];
|
u8 dataOld = tracks[track][byte];
|
||||||
u8 bitMask = 1 << bit;
|
u8 bitMask = 1 << bit;
|
||||||
if (value)
|
if (value)
|
||||||
|
@ -103,6 +132,7 @@ public:
|
||||||
TestDirty(track, (dataOld & bitMask) != 0);
|
TestDirty(track, (dataOld & bitMask) != 0);
|
||||||
tracks[track][byte] &= ~bitMask;
|
tracks[track][byte] &= ~bitMask;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char SectorsPerTrack[42];
|
static const unsigned char SectorsPerTrack[42];
|
||||||
|
@ -160,7 +190,11 @@ public:
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
unsigned char tracks[HALF_TRACK_COUNT * MAX_TRACK_LENGTH];
|
||||||
|
#else
|
||||||
unsigned char tracks[HALF_TRACK_COUNT][MAX_TRACK_LENGTH];
|
unsigned char tracks[HALF_TRACK_COUNT][MAX_TRACK_LENGTH];
|
||||||
|
#endif
|
||||||
unsigned char tracksD81[HALF_TRACK_COUNT][2][MAX_TRACK_LENGTH];
|
unsigned char tracksD81[HALF_TRACK_COUNT][2][MAX_TRACK_LENGTH];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
321
src/Drive.cpp
321
src/Drive.cpp
|
@ -346,12 +346,20 @@ extern "C"
|
||||||
|
|
||||||
Drive::Drive() : m_pVIA(0)
|
Drive::Drive() : m_pVIA(0)
|
||||||
{
|
{
|
||||||
Reset();
|
|
||||||
srand(0x811c9dc5U);
|
srand(0x811c9dc5U);
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
localSeed = 0x811c9dc5U;
|
||||||
|
#endif
|
||||||
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Drive::Reset()
|
void Drive::Reset()
|
||||||
{
|
{
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
LED = false;
|
||||||
|
cyclesForBit = 0;
|
||||||
|
UE7Counter = 16;
|
||||||
|
#endif
|
||||||
headTrackPos = 18*2; // Start with the head over track 19 (Very later Vorpal ie Cakifornia Games) need to have had the last head movement -ve
|
headTrackPos = 18*2; // Start with the head over track 19 (Very later Vorpal ie Cakifornia Games) need to have had the last head movement -ve
|
||||||
CLOCK_SEL_AB = 3; // Track 18 will use speed zone 3 (encoder/decoder (ie UE7Counter) clocked at 1.2307Mhz)
|
CLOCK_SEL_AB = 3; // Track 18 will use speed zone 3 (encoder/decoder (ie UE7Counter) clocked at 1.2307Mhz)
|
||||||
UpdateHeadSectorPosition();
|
UpdateHeadSectorPosition();
|
||||||
|
@ -361,7 +369,12 @@ void Drive::Reset()
|
||||||
readShiftRegister = 0;
|
readShiftRegister = 0;
|
||||||
writeShiftRegister = 0;
|
writeShiftRegister = 0;
|
||||||
UE3Counter = 0;
|
UE3Counter = 0;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
ResetEncoderDecoder(18 * 16, 4 * 16);
|
||||||
|
cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit);
|
||||||
|
#else
|
||||||
ResetEncoderDecoder(18.0f, 22.0f);
|
ResetEncoderDecoder(18.0f, 22.0f);
|
||||||
|
#endif
|
||||||
newDiskImageQueuedCylesRemaining = DISK_SWAP_CYCLES_DISK_EJECTING + DISK_SWAP_CYCLES_NO_DISK + DISK_SWAP_CYCLES_DISK_INSERTING;
|
newDiskImageQueuedCylesRemaining = DISK_SWAP_CYCLES_DISK_EJECTING + DISK_SWAP_CYCLES_NO_DISK + DISK_SWAP_CYCLES_DISK_INSERTING;
|
||||||
m_pVIA->InputCA1(true); // Reset in read mode
|
m_pVIA->InputCA1(true); // Reset in read mode
|
||||||
m_pVIA->InputCB1(true);
|
m_pVIA->InputCB1(true);
|
||||||
|
@ -456,6 +469,29 @@ bool Drive::Update()
|
||||||
// UE6 provides the CPU's clock by dividing the 16Mhz clock by 16.
|
// UE6 provides the CPU's clock by dividing the 16Mhz clock by 16.
|
||||||
// UE7 (a 74ls193 4bit counter) counts up on the falling edge of the 16Mhz clock. UE7 drives the Encoder/Decoder clock.
|
// UE7 (a 74ls193 4bit counter) counts up on the falling edge of the 16Mhz clock. UE7 drives the Encoder/Decoder clock.
|
||||||
// So we need to simulate 16 cycles for every 1 CPU cycle
|
// So we need to simulate 16 cycles for every 1 CPU cycle
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
if (writing)
|
||||||
|
DriveLoopWrite();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fluxReversalCyclesLeft > 16 && cyclesLeftForBit > 16)
|
||||||
|
{
|
||||||
|
DriveLoopReadNoFluxNoCycles();
|
||||||
|
}
|
||||||
|
else if (fluxReversalCyclesLeft > 16)
|
||||||
|
{
|
||||||
|
DriveLoopReadNoFlux();
|
||||||
|
}
|
||||||
|
else if (cyclesLeftForBit > 16)
|
||||||
|
{
|
||||||
|
DriveLoopReadNoCycles();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DriveLoopRead();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
for (int cycles = 0; cycles < 16; ++cycles)
|
for (int cycles = 0; cycles < 16; ++cycles)
|
||||||
{
|
{
|
||||||
if (!writing)
|
if (!writing)
|
||||||
|
@ -534,6 +570,7 @@ bool Drive::Update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
m_pVIA->InputCA1(!SO);
|
m_pVIA->InputCA1(!SO);
|
||||||
|
|
||||||
|
@ -544,3 +581,285 @@ bool Drive::Update()
|
||||||
|
|
||||||
return dataReady;
|
return dataReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
void Drive::DriveLoopReadNoFluxNoCycles()
|
||||||
|
{
|
||||||
|
unsigned int cycles = 16;
|
||||||
|
fluxReversalCyclesLeft -= 16;
|
||||||
|
cyclesLeftForBit -= 16;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (cycles < UE7Counter)
|
||||||
|
{
|
||||||
|
UE7Counter -= cycles;
|
||||||
|
cycles = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cycles -= UE7Counter;
|
||||||
|
|
||||||
|
UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings.
|
||||||
|
// The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output.
|
||||||
|
++UF4Counter &= 0xf; // Clock and clamp UF4.
|
||||||
|
// The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock))
|
||||||
|
// - ie on counts 2, 6, 10 and 14 (2 is the only count that outputs a 1 into readShiftRegister as the MSB bits of the count NORed together for other values are 0)
|
||||||
|
if ((UF4Counter & 0x3) == 2)
|
||||||
|
{
|
||||||
|
readShiftRegister <<= 1;
|
||||||
|
readShiftRegister |= (UF4Counter == 2);
|
||||||
|
|
||||||
|
//writeShiftRegister <<= 1;
|
||||||
|
|
||||||
|
bool resetTime = ((readShiftRegister & 0x3ff) == 0x3ff);
|
||||||
|
m_pVIA->GetPortB()->SetInput(0x80, !resetTime);
|
||||||
|
if (resetTime) // if the last 10 bits are 1s then SYNC
|
||||||
|
UE3Counter = 0; // Phase lock on to byte boundary
|
||||||
|
else
|
||||||
|
UE3Counter++;
|
||||||
|
}
|
||||||
|
// UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13
|
||||||
|
else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary
|
||||||
|
{
|
||||||
|
UE3Counter = 0;
|
||||||
|
SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not.
|
||||||
|
// writeShiftRegister = readShiftRegister;
|
||||||
|
m_pVIA->GetPortA()->SetInput(readShiftRegister & 0xff);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Drive::DriveLoopReadNoFlux()
|
||||||
|
{
|
||||||
|
unsigned int minCycles;
|
||||||
|
unsigned int cycles = 16;
|
||||||
|
|
||||||
|
fluxReversalCyclesLeft -= 16;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
minCycles = min(min(cyclesLeftForBit, cycles), UE7Counter);
|
||||||
|
cyclesLeftForBit -= minCycles;
|
||||||
|
cycles -= minCycles;
|
||||||
|
UE7Counter -= minCycles;
|
||||||
|
|
||||||
|
if (cycles == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (cyclesLeftForBit == 0)
|
||||||
|
{
|
||||||
|
cyclesForBitErrorCounter -= cyclesPerBitErrorConstant;
|
||||||
|
cyclesLeftForBit = cyclesPerBitInt + (cyclesForBitErrorCounter < cyclesPerBitErrorConstant);
|
||||||
|
|
||||||
|
//cyclesForBit -= cyclesPerBit;
|
||||||
|
//cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit);
|
||||||
|
//cyclesForBit += cyclesLeftForBit;
|
||||||
|
|
||||||
|
if (GetNextBit())
|
||||||
|
{
|
||||||
|
ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16);
|
||||||
|
}
|
||||||
|
if (cycles < UE7Counter)
|
||||||
|
{
|
||||||
|
UE7Counter -= cycles;
|
||||||
|
cyclesLeftForBit -= cycles;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cyclesLeftForBit -= UE7Counter;
|
||||||
|
cycles -= UE7Counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (UE7Counter == 0x0) // The count carry (bit 4) clocks UF4.
|
||||||
|
{
|
||||||
|
UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings.
|
||||||
|
// The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output.
|
||||||
|
++UF4Counter &= 0xf; // Clock and clamp UF4.
|
||||||
|
// The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock))
|
||||||
|
// - ie on counts 2, 6, 10 and 14 (2 is the only count that outputs a 1 into readShiftRegister as the MSB bits of the count NORed together for other values are 0)
|
||||||
|
if ((UF4Counter & 0x3) == 2)
|
||||||
|
{
|
||||||
|
readShiftRegister <<= 1;
|
||||||
|
readShiftRegister |= (UF4Counter == 2);
|
||||||
|
|
||||||
|
//writeShiftRegister <<= 1;
|
||||||
|
|
||||||
|
bool resetTime = ((readShiftRegister & 0x3ff) == 0x3ff);
|
||||||
|
m_pVIA->GetPortB()->SetInput(0x80, !resetTime);
|
||||||
|
if (resetTime) // if the last 10 bits are 1s then SYNC
|
||||||
|
UE3Counter = 0; // Phase lock on to byte boundary
|
||||||
|
else
|
||||||
|
UE3Counter++;
|
||||||
|
}
|
||||||
|
// UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13
|
||||||
|
else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary
|
||||||
|
{
|
||||||
|
UE3Counter = 0;
|
||||||
|
SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not.
|
||||||
|
// writeShiftRegister = readShiftRegister;
|
||||||
|
m_pVIA->GetPortA()->SetInput(readShiftRegister & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
void Drive::DriveLoopReadNoCycles()
|
||||||
|
{
|
||||||
|
unsigned int minCycles;
|
||||||
|
unsigned int cycles = 16;
|
||||||
|
|
||||||
|
cyclesLeftForBit -= 16;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
minCycles = min(cycles, min(UE7Counter, fluxReversalCyclesLeft));
|
||||||
|
fluxReversalCyclesLeft -= minCycles;
|
||||||
|
cycles -= minCycles;
|
||||||
|
UE7Counter -= minCycles;
|
||||||
|
|
||||||
|
if (cycles == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fluxReversalCyclesLeft == 0)//Not entirely right, a flux reversal will be skipped if a bit read was going to happen
|
||||||
|
{
|
||||||
|
ResetEncoderDecoder(2 * 16, /*25 * 16*/23 * 16); // Trigger a random noise generated zero crossing and start seeing more anywhere between 2us and 25us after this one.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UE7Counter == 0x0) // The count carry (bit 4) clocks UF4.
|
||||||
|
{
|
||||||
|
UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings.
|
||||||
|
// The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output.
|
||||||
|
++UF4Counter &= 0xf; // Clock and clamp UF4.
|
||||||
|
// The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock))
|
||||||
|
// - ie on counts 2, 6, 10 and 14 (2 is the only count that outputs a 1 into readShiftRegister as the MSB bits of the count NORed together for other values are 0)
|
||||||
|
if ((UF4Counter & 0x3) == 2)
|
||||||
|
{
|
||||||
|
readShiftRegister <<= 1;
|
||||||
|
readShiftRegister |= (UF4Counter == 2);
|
||||||
|
|
||||||
|
//writeShiftRegister <<= 1;
|
||||||
|
|
||||||
|
bool resetTime = ((readShiftRegister & 0x3ff) == 0x3ff);
|
||||||
|
m_pVIA->GetPortB()->SetInput(0x80, !resetTime);
|
||||||
|
if (resetTime) // if the last 10 bits are 1s then SYNC
|
||||||
|
UE3Counter = 0; // Phase lock on to byte boundary
|
||||||
|
else
|
||||||
|
UE3Counter++;
|
||||||
|
}
|
||||||
|
// UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13
|
||||||
|
else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary
|
||||||
|
{
|
||||||
|
UE3Counter = 0;
|
||||||
|
SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not.
|
||||||
|
// writeShiftRegister = readShiftRegister;
|
||||||
|
m_pVIA->GetPortA()->SetInput(readShiftRegister & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Drive::DriveLoopRead()
|
||||||
|
{
|
||||||
|
unsigned int minCycles;
|
||||||
|
unsigned int cycles = 16;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
minCycles = min(min(cyclesLeftForBit, cycles), min(UE7Counter, fluxReversalCyclesLeft));
|
||||||
|
cyclesLeftForBit -= minCycles;
|
||||||
|
fluxReversalCyclesLeft -= minCycles;
|
||||||
|
cycles -= minCycles;
|
||||||
|
UE7Counter -= minCycles;
|
||||||
|
|
||||||
|
if (cycles == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (cyclesLeftForBit == 0)
|
||||||
|
{
|
||||||
|
cyclesForBitErrorCounter -= cyclesPerBitErrorConstant;
|
||||||
|
cyclesLeftForBit = cyclesPerBitInt + (cyclesForBitErrorCounter < cyclesPerBitErrorConstant);
|
||||||
|
|
||||||
|
if (GetNextBit())
|
||||||
|
{
|
||||||
|
ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fluxReversalCyclesLeft == 0)//Not entirely right, a flux reversal will be skipped if a bit read was going to happen
|
||||||
|
{
|
||||||
|
ResetEncoderDecoder(2 * 16, /*25 * 16*/23 * 16); // Trigger a random noise generated zero crossing and start seeing more anywhere between 2us and 25us after this one.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UE7Counter == 0x0) // The count carry (bit 4) clocks UF4.
|
||||||
|
{
|
||||||
|
UE7Counter = 16-CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings.
|
||||||
|
// The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output.
|
||||||
|
++UF4Counter &= 0xf; // Clock and clamp UF4.
|
||||||
|
// The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock))
|
||||||
|
// - ie on counts 2, 6, 10 and 14 (2 is the only count that outputs a 1 into readShiftRegister as the MSB bits of the count NORed together for other values are 0)
|
||||||
|
if ((UF4Counter & 0x3) == 2)
|
||||||
|
{
|
||||||
|
readShiftRegister <<= 1;
|
||||||
|
readShiftRegister |= (UF4Counter == 2);
|
||||||
|
|
||||||
|
//writeShiftRegister <<= 1;
|
||||||
|
|
||||||
|
bool resetTime = ((readShiftRegister & 0x3ff) == 0x3ff);
|
||||||
|
m_pVIA->GetPortB()->SetInput(0x80, !resetTime);
|
||||||
|
if (resetTime) // if the last 10 bits are 1s then SYNC
|
||||||
|
UE3Counter = 0; // Phase lock on to byte boundary
|
||||||
|
else
|
||||||
|
UE3Counter++;
|
||||||
|
}
|
||||||
|
// UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13
|
||||||
|
else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary
|
||||||
|
{
|
||||||
|
UE3Counter = 0;
|
||||||
|
SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not.
|
||||||
|
// writeShiftRegister = readShiftRegister;
|
||||||
|
m_pVIA->GetPortA()->SetInput(readShiftRegister & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Drive::DriveLoopWrite()
|
||||||
|
{
|
||||||
|
unsigned int cycles = 16;
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
if (cycles < UE7Counter)
|
||||||
|
{
|
||||||
|
UE7Counter -= cycles;
|
||||||
|
cycles = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cycles -= UE7Counter;
|
||||||
|
|
||||||
|
UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings.
|
||||||
|
// The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output.
|
||||||
|
++UF4Counter &= 0xf; // Clock and clamp UF4.
|
||||||
|
// The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock))
|
||||||
|
// - ie on counts 2, 6, 10 and 14 (2 is the only count that outputs a 1 into readShiftRegister as the MSB bits of the count NORed together for other values are 0)
|
||||||
|
if ((UF4Counter & 0x3) == 2)
|
||||||
|
{
|
||||||
|
readShiftRegister <<= 1;
|
||||||
|
readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell)
|
||||||
|
|
||||||
|
SetNextBit((writeShiftRegister & 0x80));
|
||||||
|
|
||||||
|
writeShiftRegister <<= 1;
|
||||||
|
// Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs.
|
||||||
|
UE3Counter++;
|
||||||
|
}
|
||||||
|
// UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13
|
||||||
|
else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary
|
||||||
|
{
|
||||||
|
UE3Counter = 0;
|
||||||
|
SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not.
|
||||||
|
writeShiftRegister = m_pVIA->GetPortA()->GetOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
78
src/Drive.h
78
src/Drive.h
|
@ -23,6 +23,17 @@
|
||||||
#include "DiskImage.h"
|
#include "DiskImage.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
inline int ceil(float num) {
|
||||||
|
int inum = (int)num;
|
||||||
|
if (num == (float)inum) {
|
||||||
|
return inum;
|
||||||
|
}
|
||||||
|
return inum + 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class Drive
|
class Drive
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -37,6 +48,14 @@ public:
|
||||||
static void OnPortOut(void*, unsigned char status);
|
static void OnPortOut(void*, unsigned char status);
|
||||||
|
|
||||||
bool Update();
|
bool Update();
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
void DriveLoopWrite();
|
||||||
|
void DriveLoopRead();
|
||||||
|
void DriveLoopReadNoFluxNoCycles();
|
||||||
|
void DriveLoopReadNoFlux();
|
||||||
|
void DriveLoopReadNoCycles();
|
||||||
|
#endif
|
||||||
|
|
||||||
void Insert(DiskImage* diskImage);
|
void Insert(DiskImage* diskImage);
|
||||||
inline const DiskImage* GetDiskImage() const { return diskImage; }
|
inline const DiskImage* GetDiskImage() const { return diskImage; }
|
||||||
void Eject();
|
void Eject();
|
||||||
|
@ -49,6 +68,16 @@ public:
|
||||||
|
|
||||||
inline unsigned char GetLastHeadDirection() const { return lastHeadDirection; } // For simulated head movement sounds
|
inline unsigned char GetLastHeadDirection() const { return lastHeadDirection; } // For simulated head movement sounds
|
||||||
private:
|
private:
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
int32_t localSeed;
|
||||||
|
inline void ResetEncoderDecoder(unsigned int min, unsigned int /*max*/span)
|
||||||
|
{
|
||||||
|
UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6)
|
||||||
|
UF4Counter = 0;
|
||||||
|
localSeed = ((localSeed * 1103515245) + 12345) & 0x7fffffff;
|
||||||
|
fluxReversalCyclesLeft = (span) * (localSeed >> 11) + min;
|
||||||
|
}
|
||||||
|
#else
|
||||||
inline float GenerateRandomFluxReversalTime(float min, float max) { return ((max - min) * ((float)rand() / RAND_MAX)) + min; } // Inputs in micro seconds
|
inline float GenerateRandomFluxReversalTime(float min, float max) { return ((max - min) * ((float)rand() / RAND_MAX)) + min; } // Inputs in micro seconds
|
||||||
|
|
||||||
inline void ResetEncoderDecoder(float min, float max)
|
inline void ResetEncoderDecoder(float min, float max)
|
||||||
|
@ -57,6 +86,7 @@ private:
|
||||||
UF4Counter = 0;
|
UF4Counter = 0;
|
||||||
randomFluxReversalTime = GenerateRandomFluxReversalTime(min, max);
|
randomFluxReversalTime = GenerateRandomFluxReversalTime(min, max);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
inline void UpdateHeadSectorPosition()
|
inline void UpdateHeadSectorPosition()
|
||||||
{
|
{
|
||||||
// Disk spins at 300rpm = 5rps so to calculate how many 16Mhz cycles one rotation takes;-
|
// Disk spins at 300rpm = 5rps so to calculate how many 16Mhz cycles one rotation takes;-
|
||||||
|
@ -66,6 +96,12 @@ private:
|
||||||
bitsInTrack = diskImage->BitsInTrack(headTrackPos);
|
bitsInTrack = diskImage->BitsInTrack(headTrackPos);
|
||||||
headBitOffset %= bitsInTrack;
|
headBitOffset %= bitsInTrack;
|
||||||
cyclesPerBit = CYCLES_16Mhz_PER_ROTATION / (float)bitsInTrack;
|
cyclesPerBit = CYCLES_16Mhz_PER_ROTATION / (float)bitsInTrack;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
cyclesPerBitInt = cyclesPerBit;
|
||||||
|
cyclesPerBitErrorConstant = (unsigned int)((cyclesPerBit - ((float)cyclesPerBitInt)) * static_cast<float>(0xffffffff));
|
||||||
|
cyclesForBitErrorCounter = (unsigned int)(((cyclesForBit)-(int)(cyclesForBit)) * static_cast<float>(0xffffffff));
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void MoveHead(unsigned char headDirection)
|
inline void MoveHead(unsigned char headDirection)
|
||||||
|
@ -88,6 +124,15 @@ private:
|
||||||
|
|
||||||
void DumpTrack(unsigned track); // Used for debugging disk images.
|
void DumpTrack(unsigned track); // Used for debugging disk images.
|
||||||
|
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
inline u32 AdvanceSectorPositionR(int& byteOffset)
|
||||||
|
{
|
||||||
|
if (++headBitOffset == bitsInTrack)
|
||||||
|
headBitOffset = 0;
|
||||||
|
byteOffset = headBitOffset >> 3;
|
||||||
|
return (~headBitOffset) & 7;
|
||||||
|
}
|
||||||
|
#else
|
||||||
// No reason why I seperate these into individual read and write versions. I was just trying to get the bit stream to line up when rewriting over existing data.
|
// No reason why I seperate these into individual read and write versions. I was just trying to get the bit stream to line up when rewriting over existing data.
|
||||||
inline u32 AdvanceSectorPositionR(int& byteOffset)
|
inline u32 AdvanceSectorPositionR(int& byteOffset)
|
||||||
{
|
{
|
||||||
|
@ -95,7 +140,7 @@ private:
|
||||||
byteOffset = headBitOffset >> 3;
|
byteOffset = headBitOffset >> 3;
|
||||||
return (~headBitOffset) & 7;
|
return (~headBitOffset) & 7;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
inline u32 AdvanceSectorPositionW(int& byteOffset)
|
inline u32 AdvanceSectorPositionW(int& byteOffset)
|
||||||
{
|
{
|
||||||
byteOffset = headBitOffset >> 3;
|
byteOffset = headBitOffset >> 3;
|
||||||
|
@ -103,12 +148,24 @@ private:
|
||||||
++headBitOffset %= bitsInTrack;
|
++headBitOffset %= bitsInTrack;
|
||||||
return bit;
|
return bit;
|
||||||
}
|
}
|
||||||
|
unsigned cachedheadTrackPos = -1;
|
||||||
|
int cachedbyteOffset = -1;
|
||||||
|
unsigned char cachedByte = 0;
|
||||||
inline bool GetNextBit()
|
inline bool GetNextBit()
|
||||||
{
|
{
|
||||||
int byteOffset;
|
int byteOffset;
|
||||||
int bit = AdvanceSectorPositionR(byteOffset);
|
int bit = AdvanceSectorPositionR(byteOffset);
|
||||||
return diskImage->GetNextBit(headTrackPos, byteOffset, bit);
|
|
||||||
|
//Why is it faster to check both conditions here than to update the cache when moving the head?
|
||||||
|
if (byteOffset != cachedbyteOffset || cachedheadTrackPos != headTrackPos)
|
||||||
|
{
|
||||||
|
cachedByte = diskImage->GetNextByte(headTrackPos, byteOffset);
|
||||||
|
cachedbyteOffset = byteOffset;
|
||||||
|
cachedheadTrackPos = headTrackPos;
|
||||||
|
|
||||||
|
}
|
||||||
|
return ((cachedByte >> bit) & 1) != 0;
|
||||||
|
//return diskImage->GetNextBit(headTrackPos, byteOffset, bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetNextBit(bool value)
|
inline void SetNextBit(bool value)
|
||||||
|
@ -132,13 +189,23 @@ private:
|
||||||
// CB2 (output)
|
// CB2 (output)
|
||||||
// - R/!W
|
// - R/!W
|
||||||
m6522* m_pVIA;
|
m6522* m_pVIA;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
unsigned int cyclesLeftForBit;
|
||||||
|
unsigned int fluxReversalCyclesLeft;
|
||||||
|
unsigned int UE7Counter;
|
||||||
|
u32 writeShiftRegister;
|
||||||
|
unsigned int cyclesForBitErrorCounter;
|
||||||
|
unsigned int cyclesPerBitErrorConstant;
|
||||||
|
unsigned int cyclesPerBitInt;
|
||||||
|
#else
|
||||||
|
int UE7Counter;
|
||||||
|
u8 writeShiftRegister;
|
||||||
|
#endif
|
||||||
float cyclesForBit;
|
float cyclesForBit;
|
||||||
u32 readShiftRegister;
|
u32 readShiftRegister;
|
||||||
unsigned headTrackPos;
|
unsigned headTrackPos;
|
||||||
u32 headBitOffset;
|
u32 headBitOffset;
|
||||||
float randomFluxReversalTime;
|
float randomFluxReversalTime;
|
||||||
int UE7Counter;
|
|
||||||
int UF4Counter;
|
int UF4Counter;
|
||||||
int UE3Counter;
|
int UE3Counter;
|
||||||
int CLOCK_SEL_AB;
|
int CLOCK_SEL_AB;
|
||||||
|
@ -148,6 +215,5 @@ private:
|
||||||
float cyclesPerBit;
|
float cyclesPerBit;
|
||||||
bool motor;
|
bool motor;
|
||||||
bool LED;
|
bool LED;
|
||||||
u8 writeShiftRegister;
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -113,7 +113,6 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b
|
||||||
}
|
}
|
||||||
int len = strlen(buffer2 + highlightScrollOffset);
|
int len = strlen(buffer2 + highlightScrollOffset);
|
||||||
strncpy(buffer1, buffer2 + highlightScrollOffset, sizeof(buffer1));
|
strncpy(buffer1, buffer2 + highlightScrollOffset, sizeof(buffer1));
|
||||||
|
|
||||||
if (!screen->IsLCD())
|
if (!screen->IsLCD())
|
||||||
{
|
{
|
||||||
// space pad the remainder of the line (but not on OLED)
|
// space pad the remainder of the line (but not on OLED)
|
||||||
|
@ -121,7 +120,6 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b
|
||||||
buffer1[len++] = ' ';
|
buffer1[len++] = ' ';
|
||||||
buffer1[columnsMax] = 0;
|
buffer1[columnsMax] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected)
|
if (selected)
|
||||||
{
|
{
|
||||||
if (entry->filImage.fattrib & AM_DIR)
|
if (entry->filImage.fattrib & AM_DIR)
|
||||||
|
@ -133,7 +131,6 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b
|
||||||
colour = RGBA(0xff, 0, 0, 0xff);
|
colour = RGBA(0xff, 0, 0, 0xff);
|
||||||
if (entry->filImage.fattrib & AM_RDO)
|
if (entry->filImage.fattrib & AM_RDO)
|
||||||
colour = palette[VIC2_COLOUR_INDEX_RED];
|
colour = palette[VIC2_COLOUR_INDEX_RED];
|
||||||
|
|
||||||
screen->PrintText(false, x, y, buffer1, colour, RGBA(0xff, 0xff, 0xff, 0xff));
|
screen->PrintText(false, x, y, buffer1, colour, RGBA(0xff, 0xff, 0xff, 0xff));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -499,11 +496,17 @@ FileBrowser::FileBrowser(InputMappings* inputMappings, DiskCaddy* diskCaddy, ROM
|
||||||
, roms(roms)
|
, roms(roms)
|
||||||
, deviceID(deviceID)
|
, deviceID(deviceID)
|
||||||
, displayPNGIcons(displayPNGIcons)
|
, displayPNGIcons(displayPNGIcons)
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
, screenMain(screenMain)
|
, screenMain(screenMain)
|
||||||
|
#endif
|
||||||
, screenLCD(screenLCD)
|
, screenLCD(screenLCD)
|
||||||
, scrollHighlightRate(scrollHighlightRate)
|
, scrollHighlightRate(scrollHighlightRate)
|
||||||
, displayingDevices(false)
|
, displayingDevices(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
folder.scrollHighlightRate = scrollHighlightRate;
|
||||||
|
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
u32 columns = screenMain->ScaleX(80);
|
u32 columns = screenMain->ScaleX(80);
|
||||||
u32 rows = (int)(38.0f * screenMain->GetScaleY());
|
u32 rows = (int)(38.0f * screenMain->GetScaleY());
|
||||||
u32 positionX = 0;
|
u32 positionX = 0;
|
||||||
|
@ -512,7 +515,6 @@ FileBrowser::FileBrowser(InputMappings* inputMappings, DiskCaddy* diskCaddy, ROM
|
||||||
if (rows < 1)
|
if (rows < 1)
|
||||||
rows = 1;
|
rows = 1;
|
||||||
|
|
||||||
folder.scrollHighlightRate = scrollHighlightRate;
|
|
||||||
folder.AddView(screenMain, inputMappings, columns, rows, positionX, positionY, false);
|
folder.AddView(screenMain, inputMappings, columns, rows, positionX, positionY, false);
|
||||||
|
|
||||||
positionX = screenMain->ScaleX(1024 - 320);
|
positionX = screenMain->ScaleX(1024 - 320);
|
||||||
|
@ -520,13 +522,14 @@ FileBrowser::FileBrowser(InputMappings* inputMappings, DiskCaddy* diskCaddy, ROM
|
||||||
caddySelections.AddView(screenMain, inputMappings, columns, rows, positionX, positionY, false);
|
caddySelections.AddView(screenMain, inputMappings, columns, rows, positionX, positionY, false);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
if (screenLCD)
|
if (screenLCD)
|
||||||
{
|
{
|
||||||
columns = screenLCD->Width() / 8;
|
u32 columns = screenLCD->Width() / 8;
|
||||||
rows = screenLCD->Height() / screenLCD->GetFontHeight();
|
u32 rows = screenLCD->Height() / screenLCD->GetFontHeight();
|
||||||
positionX = 0;
|
u32 positionX = 0;
|
||||||
positionY = 0;
|
u32 positionY = 0;
|
||||||
|
|
||||||
folder.AddView(screenLCD, inputMappings, columns, rows, positionX, positionY, true);
|
folder.AddView(screenLCD, inputMappings, columns, rows, positionX, positionY, true);
|
||||||
}
|
}
|
||||||
|
@ -690,7 +693,6 @@ void FileBrowser::DeviceSwitched()
|
||||||
m_IEC_Commands.SetDisplayingDevices(displayingDevices);
|
m_IEC_Commands.SetDisplayingDevices(displayingDevices);
|
||||||
FolderChanged();
|
FolderChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void FileBrowser::RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* browsableList, int xOffset, bool showSelected)
|
void FileBrowser::RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* browsableList, int xOffset, bool showSelected)
|
||||||
{
|
{
|
||||||
|
@ -769,9 +771,9 @@ void FileBrowser::RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* brow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void FileBrowser::RefeshDisplay()
|
void FileBrowser::RefeshDisplay()
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
u32 textColour = Colour(VIC2_COLOUR_INDEX_LGREEN);
|
u32 textColour = Colour(VIC2_COLOUR_INDEX_LGREEN);
|
||||||
u32 bgColour = Colour(VIC2_COLOUR_INDEX_GREY);
|
u32 bgColour = Colour(VIC2_COLOUR_INDEX_GREY);
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
|
@ -780,11 +782,9 @@ void FileBrowser::RefeshDisplay()
|
||||||
screenMain->DrawRectangle(0, 0, (int)screenMain->Width(), 17, bgColour);
|
screenMain->DrawRectangle(0, 0, (int)screenMain->Width(), 17, bgColour);
|
||||||
screenMain->PrintText(false, 0, 0, buffer, textColour, bgColour);
|
screenMain->PrintText(false, 0, 0, buffer, textColour, bgColour);
|
||||||
}
|
}
|
||||||
|
|
||||||
//u32 offsetX = screenMain->ScaleX(1024 - 320);
|
//u32 offsetX = screenMain->ScaleX(1024 - 320);
|
||||||
//RefeshDisplayForBrowsableList(&folder, 0);
|
//RefeshDisplayForBrowsableList(&folder, 0);
|
||||||
//RefeshDisplayForBrowsableList(&caddySelections, offsetX, false);
|
//RefeshDisplayForBrowsableList(&caddySelections, offsetX, false);
|
||||||
|
|
||||||
folder.RefreshViews();
|
folder.RefreshViews();
|
||||||
caddySelections.RefreshViews();
|
caddySelections.RefreshViews();
|
||||||
|
|
||||||
|
@ -796,6 +796,10 @@ void FileBrowser::RefeshDisplay()
|
||||||
u32 y = screenMain->ScaleY(STATUS_BAR_POSITION_Y);
|
u32 y = screenMain->ScaleY(STATUS_BAR_POSITION_Y);
|
||||||
screenMain->PrintText(false, 0, y, folder.searchPrefix, textColour, bgColour);
|
screenMain->PrintText(false, 0, y, folder.searchPrefix, textColour, bgColour);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
folder.RefreshViews();
|
||||||
|
caddySelections.RefreshViews();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileBrowser::CheckForPNG(const char* filename, FILINFO& filIcon)
|
bool FileBrowser::CheckForPNG(const char* filename, FILINFO& filIcon)
|
||||||
|
@ -843,6 +847,8 @@ void FileBrowser::DisplayPNG(FILINFO& filIcon, int x, int y)
|
||||||
int h;
|
int h;
|
||||||
int channels_in_file;
|
int channels_in_file;
|
||||||
stbi_uc* image = stbi_load_from_memory((stbi_uc const*)PNG, bytesRead, &w, &h, &channels_in_file, 4);
|
stbi_uc* image = stbi_load_from_memory((stbi_uc const*)PNG, bytesRead, &w, &h, &channels_in_file, 4);
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
|
|
||||||
if (image && (w == PNG_WIDTH && h == PNG_HEIGHT))
|
if (image && (w == PNG_WIDTH && h == PNG_HEIGHT))
|
||||||
{
|
{
|
||||||
//DEBUG_LOG("Opened PNG %s w = %d h = %d cif = %d\r\n", fileName, w, h, channels_in_file);
|
//DEBUG_LOG("Opened PNG %s w = %d h = %d cif = %d\r\n", fileName, w, h, channels_in_file);
|
||||||
|
@ -852,6 +858,7 @@ void FileBrowser::DisplayPNG(FILINFO& filIcon, int x, int y)
|
||||||
{
|
{
|
||||||
//DEBUG_LOG("Invalid PNG size %d x %d\r\n", w, h);
|
//DEBUG_LOG("Invalid PNG size %d x %d\r\n", w, h);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -862,6 +869,7 @@ void FileBrowser::DisplayPNG(FILINFO& filIcon, int x, int y)
|
||||||
|
|
||||||
void FileBrowser::DisplayPNG()
|
void FileBrowser::DisplayPNG()
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
if (displayPNGIcons && folder.current)
|
if (displayPNGIcons && folder.current)
|
||||||
{
|
{
|
||||||
FileBrowser::BrowsableList::Entry* current = folder.current;
|
FileBrowser::BrowsableList::Entry* current = folder.current;
|
||||||
|
@ -869,6 +877,7 @@ void FileBrowser::DisplayPNG()
|
||||||
u32 y = screenMain->ScaleY(666) - PNG_HEIGHT;
|
u32 y = screenMain->ScaleY(666) - PNG_HEIGHT;
|
||||||
DisplayPNG(current->filIcon, x, y);
|
DisplayPNG(current->filIcon, x, y);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int FileBrowser::IsAtRootOfDevice()
|
int FileBrowser::IsAtRootOfDevice()
|
||||||
|
@ -1369,18 +1378,22 @@ void FileBrowser::UpdateInputDiskCaddy()
|
||||||
|
|
||||||
void FileBrowser::DisplayStatusBar()
|
void FileBrowser::DisplayStatusBar()
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
u32 x = 0;
|
u32 x = 0;
|
||||||
u32 y = screenMain->ScaleY(STATUS_BAR_POSITION_Y);
|
u32 y = screenMain->ScaleY(STATUS_BAR_POSITION_Y);
|
||||||
|
|
||||||
char bufferOut[128];
|
char bufferOut[128];
|
||||||
snprintf(bufferOut, 128, "LED 0 Motor 0 Track 18.0 ATN 0 DAT 0 CLK 0");
|
snprintf(bufferOut, 128, "LED 0 Motor 0 Track 18.0 ATN 0 DAT 0 CLK 0");
|
||||||
screenMain->PrintText(false, x, y, bufferOut, RGBA(0, 0, 0, 0xff), RGBA(0xff, 0xff, 0xff, 0xff));
|
screenMain->PrintText(false, x, y, bufferOut, RGBA(0, 0, 0, 0xff), RGBA(0xff, 0xff, 0xff, 0xff));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowser::ClearScreen()
|
void FileBrowser::ClearScreen()
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
u32 bgColour = palette[VIC2_COLOUR_INDEX_BLUE];
|
u32 bgColour = palette[VIC2_COLOUR_INDEX_BLUE];
|
||||||
screenMain->Clear(bgColour);
|
screenMain->Clear(bgColour);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowser::ClearSelections()
|
void FileBrowser::ClearSelections()
|
||||||
|
@ -1397,6 +1410,7 @@ void FileBrowser::ShowDeviceAndROM()
|
||||||
u32 textColour = RGBA(0, 0, 0, 0xff);
|
u32 textColour = RGBA(0, 0, 0, 0xff);
|
||||||
u32 bgColour = RGBA(0xff, 0xff, 0xff, 0xff);
|
u32 bgColour = RGBA(0xff, 0xff, 0xff, 0xff);
|
||||||
u32 x = 0; // 43 * 8
|
u32 x = 0; // 43 * 8
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
u32 y = screenMain->ScaleY(STATUS_BAR_POSITION_Y) - 20;
|
u32 y = screenMain->ScaleY(STATUS_BAR_POSITION_Y) - 20;
|
||||||
|
|
||||||
snprintf(buffer, 256, "Device %2d %*s\r\n"
|
snprintf(buffer, 256, "Device %2d %*s\r\n"
|
||||||
|
@ -1405,10 +1419,12 @@ void FileBrowser::ShowDeviceAndROM()
|
||||||
, roms->ROMNames[roms->currentROMIndex]
|
, roms->ROMNames[roms->currentROMIndex]
|
||||||
);
|
);
|
||||||
screenMain->PrintText(false, x, y, buffer, textColour, bgColour);
|
screenMain->PrintText(false, x, y, buffer, textColour, bgColour);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForIcon)
|
void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForIcon)
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
// Ideally we should not have to load the entire disk to read the directory.
|
// Ideally we should not have to load the entire disk to read the directory.
|
||||||
static const char* fileTypes[]=
|
static const char* fileTypes[]=
|
||||||
{
|
{
|
||||||
|
@ -1626,6 +1642,7 @@ void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForI
|
||||||
DisplayPNG(filIcon, x, y);
|
DisplayPNG(filIcon, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowser::SelectAutoMountImage(const char* image)
|
void FileBrowser::SelectAutoMountImage(const char* image)
|
||||||
|
|
|
@ -84,7 +84,6 @@ public:
|
||||||
BrowsableList* list;
|
BrowsableList* list;
|
||||||
u32 offset;
|
u32 offset;
|
||||||
InputMappings* inputMappings;
|
InputMappings* inputMappings;
|
||||||
|
|
||||||
ScreenBase* screen;
|
ScreenBase* screen;
|
||||||
u32 columns;
|
u32 columns;
|
||||||
u32 rows;
|
u32 rows;
|
||||||
|
@ -215,9 +214,7 @@ private:
|
||||||
//void UpdateInputDiskCaddy();
|
//void UpdateInputDiskCaddy();
|
||||||
|
|
||||||
void UpdateCurrentHighlight();
|
void UpdateCurrentHighlight();
|
||||||
|
|
||||||
//void RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* browsableList, int xOffset, bool showSelected = true);
|
//void RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* browsableList, int xOffset, bool showSelected = true);
|
||||||
|
|
||||||
bool FillCaddyWithSelections();
|
bool FillCaddyWithSelections();
|
||||||
|
|
||||||
bool AddToCaddy(FileBrowser::BrowsableList::Entry* current);
|
bool AddToCaddy(FileBrowser::BrowsableList::Entry* current);
|
||||||
|
@ -249,10 +246,10 @@ private:
|
||||||
bool buttonChangedROMDevice;
|
bool buttonChangedROMDevice;
|
||||||
|
|
||||||
BrowsableList caddySelections;
|
BrowsableList caddySelections;
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
ScreenBase* screenMain;
|
ScreenBase* screenMain;
|
||||||
|
#endif
|
||||||
ScreenBase* screenLCD;
|
ScreenBase* screenLCD;
|
||||||
|
|
||||||
float scrollHighlightRate;
|
float scrollHighlightRate;
|
||||||
|
|
||||||
bool displayingDevices;
|
bool displayingDevices;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
// Pi1541 - A Commodore 1541 disk drive emulator
|
// Pi1541 - A Commodore 1541 disk drive emulator
|
||||||
// Copyright(C) 2018 Stephen White
|
// Copyright(C) 2018 Stephen White
|
||||||
//
|
//
|
||||||
|
@ -217,9 +218,11 @@ void InputMappings::CheckButtonsEmulationMode()
|
||||||
|
|
||||||
bool InputMappings::CheckKeyboardBrowseMode()
|
bool InputMappings::CheckKeyboardBrowseMode()
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
Keyboard* keyboard = Keyboard::Instance();
|
Keyboard* keyboard = Keyboard::Instance();
|
||||||
|
#endif
|
||||||
keyboardFlags = 0;
|
keyboardFlags = 0;
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
keyboardNumLetter = 0;
|
keyboardNumLetter = 0;
|
||||||
if (!keyboard->CheckChanged())
|
if (!keyboard->CheckChanged())
|
||||||
{
|
{
|
||||||
|
@ -305,12 +308,13 @@ bool InputMappings::CheckKeyboardBrowseMode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return keyboardFlags != 0;
|
return keyboardFlags != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputMappings::CheckKeyboardEmulationMode(unsigned numberOfImages, unsigned numberOfImagesMax)
|
void InputMappings::CheckKeyboardEmulationMode(unsigned numberOfImages, unsigned numberOfImagesMax)
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
Keyboard* keyboard = Keyboard::Instance();
|
Keyboard* keyboard = Keyboard::Instance();
|
||||||
|
|
||||||
keyboardFlags = 0;
|
keyboardFlags = 0;
|
||||||
|
@ -341,5 +345,6 @@ void InputMappings::CheckKeyboardEmulationMode(unsigned numberOfImages, unsigned
|
||||||
directDiskSwapRequest |= (1 << index);
|
directDiskSwapRequest |= (1 << index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,21 +103,37 @@ public:
|
||||||
keyboardBrowseLCDScreen = value;
|
keyboardBrowseLCDScreen = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
inline bool Exit()
|
inline bool Exit()
|
||||||
{
|
{
|
||||||
return KeyboardFlag(ESC_FLAG)/* | UartFlag(ESC_FLAG)*/ | ButtonFlag(ESC_FLAG);
|
return ButtonFlag(ESC_FLAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool NextDisk()
|
inline bool NextDisk()
|
||||||
{
|
{
|
||||||
return KeyboardFlag(NEXT_FLAG)/* | UartFlag(NEXT_FLAG)*/ | ButtonFlag(NEXT_FLAG);
|
return ButtonFlag(NEXT_FLAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PrevDisk()
|
inline bool PrevDisk()
|
||||||
{
|
{
|
||||||
return KeyboardFlag(PREV_FLAG)/* | UartFlag(PREV_FLAG)*/ | ButtonFlag(PREV_FLAG);
|
return ButtonFlag(PREV_FLAG);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
inline bool Exit()
|
||||||
|
{
|
||||||
|
return KeyboardFlag(ESC_FLAG) | /*UartFlag(ESC_FLAG) |*/ ButtonFlag(ESC_FLAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool NextDisk()
|
||||||
|
{
|
||||||
|
return KeyboardFlag(NEXT_FLAG) | /*UartFlag(NEXT_FLAG) |*/ ButtonFlag(NEXT_FLAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool PrevDisk()
|
||||||
|
{
|
||||||
|
return KeyboardFlag(PREV_FLAG) | /*UartFlag(PREV_FLAG) |*/ ButtonFlag(PREV_FLAG);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
inline bool AutoLoad() { return KeyboardFlag(AUTOLOAD_FLAG); }
|
inline bool AutoLoad() { return KeyboardFlag(AUTOLOAD_FLAG); }
|
||||||
|
|
||||||
inline bool FakeReset() { return KeyboardFlag(FAKERESET_FLAG); }
|
inline bool FakeReset() { return KeyboardFlag(FAKERESET_FLAG); }
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Pi1541. If not, see <http://www.gnu.org/licenses/>.
|
// along with Pi1541. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
#include "Keyboard.h"
|
#include "Keyboard.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <uspi.h>
|
#include <uspi.h>
|
||||||
|
@ -156,3 +156,4 @@ Keyboard::Keyboard()
|
||||||
memset(keyRepeatCount, 0, sizeof(keyRepeatCount));
|
memset(keyRepeatCount, 0, sizeof(keyRepeatCount));
|
||||||
USPiKeyboardRegisterKeyStatusHandlerRaw(KeyPressedHandlerRaw);
|
USPiKeyboardRegisterKeyStatusHandlerRaw(KeyPressedHandlerRaw);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -24,6 +24,7 @@ extern "C"
|
||||||
{
|
{
|
||||||
#include <uspi/usbkeyboard.h>
|
#include <uspi/usbkeyboard.h>
|
||||||
}
|
}
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
|
|
||||||
#define MAX_KEYS 0x7f
|
#define MAX_KEYS 0x7f
|
||||||
|
|
||||||
|
@ -356,3 +357,4 @@ public:
|
||||||
static Keyboard* instance;
|
static Keyboard* instance;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
|
@ -93,6 +93,7 @@ extern u16 pc;
|
||||||
u8 read6502_1581(u16 address)
|
u8 read6502_1581(u16 address)
|
||||||
{
|
{
|
||||||
u8 value = 0;
|
u8 value = 0;
|
||||||
|
#if defined(PI1581SUPPORT)
|
||||||
if (address & 0x8000)
|
if (address & 0x8000)
|
||||||
{
|
{
|
||||||
value = roms.Read1581(address);
|
value = roms.Read1581(address);
|
||||||
|
@ -115,6 +116,7 @@ u8 read6502_1581(u16 address)
|
||||||
{
|
{
|
||||||
value = address >> 8; // Empty address bus
|
value = address >> 8; // Empty address bus
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +129,7 @@ u8 peek6502_1581(u16 address)
|
||||||
|
|
||||||
void write6502_1581(u16 address, const u8 value)
|
void write6502_1581(u16 address, const u8 value)
|
||||||
{
|
{
|
||||||
|
#if defined(PI1581SUPPORT)
|
||||||
if (address & 0x8000)
|
if (address & 0x8000)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -145,6 +148,7 @@ void write6502_1581(u16 address, const u8 value)
|
||||||
{
|
{
|
||||||
s_u8Memory[address & 0x1fff] = value;
|
s_u8Memory[address & 0x1fff] = value;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CIAPortA_OnPortOut(void* pUserData, unsigned char status)
|
static void CIAPortA_OnPortOut(void* pUserData, unsigned char status)
|
||||||
|
|
|
@ -129,21 +129,29 @@ void Screen::Open(u32 widthDesired, u32 heightDesired, u32 colourDepth)
|
||||||
|
|
||||||
void Screen::PlotPixel32(u32 pixel_offset, RGBA Colour)
|
void Screen::PlotPixel32(u32 pixel_offset, RGBA Colour)
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
*((volatile RGBA*)&framebuffer[pixel_offset]) = Colour;
|
*((volatile RGBA*)&framebuffer[pixel_offset]) = Colour;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
void Screen::PlotPixel24(u32 pixel_offset, RGBA Colour)
|
void Screen::PlotPixel24(u32 pixel_offset, RGBA Colour)
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
framebuffer[pixel_offset++] = BLUE(Colour);
|
framebuffer[pixel_offset++] = BLUE(Colour);
|
||||||
framebuffer[pixel_offset++] = GREEN(Colour);
|
framebuffer[pixel_offset++] = GREEN(Colour);
|
||||||
framebuffer[pixel_offset++] = RED(Colour);
|
framebuffer[pixel_offset++] = RED(Colour);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
void Screen::PlotPixel16(u32 pixel_offset, RGBA Colour)
|
void Screen::PlotPixel16(u32 pixel_offset, RGBA Colour)
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
*(unsigned short*)&framebuffer[pixel_offset] = ((RED(Colour) >> 3) << 11) | ((GREEN(Colour) >> 2) << 5) | (BLUE(Colour) >> 3);
|
*(unsigned short*)&framebuffer[pixel_offset] = ((RED(Colour) >> 3) << 11) | ((GREEN(Colour) >> 2) << 5) | (BLUE(Colour) >> 3);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
void Screen::PlotPixel8(u32 pixel_offset, RGBA Colour)
|
void Screen::PlotPixel8(u32 pixel_offset, RGBA Colour)
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
framebuffer[pixel_offset++] = RED(Colour);
|
framebuffer[pixel_offset++] = RED(Colour);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::DrawRectangle(u32 x1, u32 y1, u32 x2, u32 y2, RGBA colour)
|
void Screen::DrawRectangle(u32 x1, u32 y1, u32 x2, u32 y2, RGBA colour)
|
||||||
|
|
|
@ -236,7 +236,9 @@ int wait(int *status)
|
||||||
|
|
||||||
void outbyte(char b)
|
void outbyte(char b)
|
||||||
{
|
{
|
||||||
|
#ifndef EXPERIMENTALZERO
|
||||||
RPI_AuxMiniUartWrite(b);
|
RPI_AuxMiniUartWrite(b);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write to a file. libc subroutines will use this system routine for output to
|
/* Write to a file. libc subroutines will use this system routine for output to
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
#define DEFS_H
|
#define DEFS_H
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#ifndef EXPERIMENTALZERO
|
||||||
|
#define PI1581SUPPORT 1
|
||||||
|
#endif
|
||||||
// Indicates a Pi with the 40 pin GPIO connector
|
// Indicates a Pi with the 40 pin GPIO connector
|
||||||
// so that additional functionality (e.g. test pins) can be enabled
|
// so that additional functionality (e.g. test pins) can be enabled
|
||||||
#if defined(RPIZERO) || defined(RPIBPLUS) || defined(RPI2) || defined(RPI3)
|
#if defined(RPIZERO) || defined(RPIBPLUS) || defined(RPI2) || defined(RPI3)
|
||||||
|
|
|
@ -335,10 +335,10 @@ void IEC_Bus::RefreshOuts1541(void)
|
||||||
|
|
||||||
if (OutputLED) set |= 1 << PIGPIO_OUT_LED;
|
if (OutputLED) set |= 1 << PIGPIO_OUT_LED;
|
||||||
else clear |= 1 << PIGPIO_OUT_LED;
|
else clear |= 1 << PIGPIO_OUT_LED;
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
if (OutputSound) set |= 1 << PIGPIO_OUT_SOUND;
|
if (OutputSound) set |= 1 << PIGPIO_OUT_SOUND;
|
||||||
else clear |= 1 << PIGPIO_OUT_SOUND;
|
else clear |= 1 << PIGPIO_OUT_SOUND;
|
||||||
|
#endif
|
||||||
if (oldClears != clear)
|
if (oldClears != clear)
|
||||||
{
|
{
|
||||||
write32(ARM_GPIO_GPCLR0, clear);
|
write32(ARM_GPIO_GPCLR0, clear);
|
||||||
|
|
|
@ -135,6 +135,7 @@ enum PIGPIOMasks
|
||||||
PIGPIO_MASK_IN_BUTTON3 = 1 << PIGPIO_IN_BUTTON3,
|
PIGPIO_MASK_IN_BUTTON3 = 1 << PIGPIO_IN_BUTTON3,
|
||||||
PIGPIO_MASK_IN_BUTTON4 = 1 << PIGPIO_IN_BUTTON4,
|
PIGPIO_MASK_IN_BUTTON4 = 1 << PIGPIO_IN_BUTTON4,
|
||||||
PIGPIO_MASK_IN_BUTTON5 = 1 << PIGPIO_IN_BUTTON5,
|
PIGPIO_MASK_IN_BUTTON5 = 1 << PIGPIO_IN_BUTTON5,
|
||||||
|
PIGPIO_MASK_ANY_BUTTON = PIGPIO_MASK_IN_BUTTON1 | PIGPIO_MASK_IN_BUTTON2 | PIGPIO_MASK_IN_BUTTON3 | PIGPIO_MASK_IN_BUTTON4 | PIGPIO_MASK_IN_BUTTON5
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned ButtonPinFlags[5] = { PIGPIO_MASK_IN_BUTTON1, PIGPIO_MASK_IN_BUTTON2, PIGPIO_MASK_IN_BUTTON3, PIGPIO_MASK_IN_BUTTON4, PIGPIO_MASK_IN_BUTTON5 };
|
static const unsigned ButtonPinFlags[5] = { PIGPIO_MASK_IN_BUTTON1, PIGPIO_MASK_IN_BUTTON2, PIGPIO_MASK_IN_BUTTON3, PIGPIO_MASK_IN_BUTTON4, PIGPIO_MASK_IN_BUTTON5 };
|
||||||
|
@ -276,7 +277,7 @@ public:
|
||||||
RPI_SetGpioPinFunction((rpi_gpio_pin_t)PIGPIO_OUT_SRQ, FS_OUTPUT);
|
RPI_SetGpioPinFunction((rpi_gpio_pin_t)PIGPIO_OUT_SRQ, FS_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
// Set up audio.
|
// Set up audio.
|
||||||
write32(CM_PWMDIV, CM_PASSWORD + 0x2000);
|
write32(CM_PWMDIV, CM_PASSWORD + 0x2000);
|
||||||
write32(CM_PWMCTL, CM_PASSWORD + CM_ENAB + CM_SRC_OSCILLATOR); // Use Default 100MHz Clock
|
write32(CM_PWMCTL, CM_PASSWORD + CM_ENAB + CM_SRC_OSCILLATOR); // Use Default 100MHz Clock
|
||||||
|
@ -284,7 +285,7 @@ public:
|
||||||
write32(PWM_RNG1, 0x1B4); // 8bit 44100Hz Mono
|
write32(PWM_RNG1, 0x1B4); // 8bit 44100Hz Mono
|
||||||
write32(PWM_RNG2, 0x1B4);
|
write32(PWM_RNG2, 0x1B4);
|
||||||
write32(PWM_CTL, PWM_USEF2 + PWM_PWEN2 + PWM_USEF1 + PWM_PWEN1 + PWM_CLRF1);
|
write32(PWM_CTL, PWM_USEF2 + PWM_PWEN2 + PWM_USEF1 + PWM_PWEN1 + PWM_CLRF1);
|
||||||
|
#endif
|
||||||
|
|
||||||
int buttonCount = sizeof(ButtonPinFlags) / sizeof(unsigned);
|
int buttonCount = sizeof(ButtonPinFlags) / sizeof(unsigned);
|
||||||
for (index = 0; index < buttonCount; ++index)
|
for (index = 0; index < buttonCount; ++index)
|
||||||
|
@ -316,6 +317,13 @@ public:
|
||||||
RefreshOuts1581();
|
RefreshOuts1581();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
static inline bool AnyButtonPressed()
|
||||||
|
{
|
||||||
|
return ((gplev0 & PIGPIO_MASK_ANY_BUTTON) != PIGPIO_MASK_ANY_BUTTON);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void UpdateButton(int index, unsigned gplev0)
|
static inline void UpdateButton(int index, unsigned gplev0)
|
||||||
{
|
{
|
||||||
bool inputcurrent = (gplev0 & ButtonPinFlags[index]) == 0;
|
bool inputcurrent = (gplev0 & ButtonPinFlags[index]) == 0;
|
||||||
|
|
|
@ -39,16 +39,21 @@ void InterruptSystemInitialize()
|
||||||
write32(ARM_IC_IRQ_PENDING_2, read32(ARM_IC_IRQ_PENDING_2));
|
write32(ARM_IC_IRQ_PENDING_2, read32(ARM_IC_IRQ_PENDING_2));
|
||||||
|
|
||||||
DataMemBarrier();
|
DataMemBarrier();
|
||||||
|
#ifdef EXPERIMENTALZERO
|
||||||
|
DisableInterrupts();
|
||||||
|
#else
|
||||||
EnableInterrupts();
|
EnableInterrupts();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterruptSystemConnectIRQ(unsigned IRQIndex, IRQHandler* handler, void* param)
|
void InterruptSystemConnectIRQ(unsigned IRQIndex, IRQHandler* handler, void* param)
|
||||||
{
|
{
|
||||||
|
#ifndef EXPERIMENTALZERO
|
||||||
IRQHandlers[IRQIndex] = handler;
|
IRQHandlers[IRQIndex] = handler;
|
||||||
Params[IRQIndex] = param;
|
Params[IRQIndex] = param;
|
||||||
|
|
||||||
InterruptSystemEnableIRQ(IRQIndex);
|
InterruptSystemEnableIRQ(IRQIndex);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterruptSystemDisconnectIRQ(unsigned IRQIndex)
|
void InterruptSystemDisconnectIRQ(unsigned IRQIndex)
|
||||||
|
@ -61,10 +66,12 @@ void InterruptSystemDisconnectIRQ(unsigned IRQIndex)
|
||||||
|
|
||||||
void InterruptSystemEnableIRQ(unsigned IRQIndex)
|
void InterruptSystemEnableIRQ(unsigned IRQIndex)
|
||||||
{
|
{
|
||||||
//DEBUG_LOG("InterruptSystemEnableIRQ %d\r\n", IRQIndex);
|
#ifndef EXPERIMENTALZERO
|
||||||
|
DEBUG_LOG("InterruptSystemEnableIRQ %d\r\n", IRQIndex);
|
||||||
DataMemBarrier();
|
DataMemBarrier();
|
||||||
write32(ARM_IC_IRQS_ENABLE(IRQIndex), ARM_IRQ_MASK(IRQIndex));
|
write32(ARM_IC_IRQS_ENABLE(IRQIndex), ARM_IRQ_MASK(IRQIndex));
|
||||||
DataMemBarrier();
|
DataMemBarrier();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterruptSystemDisableIRQ(unsigned IRQIndex)
|
void InterruptSystemDisableIRQ(unsigned IRQIndex)
|
||||||
|
@ -110,11 +117,13 @@ void InterruptHandler(void)
|
||||||
|
|
||||||
if (pendValue & IRQIndexMask)
|
if (pendValue & IRQIndexMask)
|
||||||
{
|
{
|
||||||
|
#ifndef EXPERIMENTALZERO
|
||||||
IRQHandler* pHandler = IRQHandlers[IRQIndex];
|
IRQHandler* pHandler = IRQHandlers[IRQIndex];
|
||||||
|
|
||||||
if (pHandler != 0)
|
if (pHandler != 0)
|
||||||
(*pHandler)(Params[IRQIndex]);
|
(*pHandler)(Params[IRQIndex]);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
InterruptSystemDisableIRQ(IRQIndex);
|
InterruptSystemDisableIRQ(IRQIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,11 +136,13 @@ void InterruptHandler(void)
|
||||||
|
|
||||||
if (pendValue & IRQIndexMask)
|
if (pendValue & IRQIndexMask)
|
||||||
{
|
{
|
||||||
|
#ifndef EXPERIMENTALZERO
|
||||||
IRQHandler* pHandler = IRQHandlers[IRQIndex];
|
IRQHandler* pHandler = IRQHandlers[IRQIndex];
|
||||||
|
|
||||||
if (pHandler != 0)
|
if (pHandler != 0)
|
||||||
(*pHandler)(Params[IRQIndex]);
|
(*pHandler)(Params[IRQIndex]);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
InterruptSystemDisableIRQ(IRQIndex);
|
InterruptSystemDisableIRQ(IRQIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,11 +155,13 @@ void InterruptHandler(void)
|
||||||
|
|
||||||
if (pendValue & IRQIndexMask)
|
if (pendValue & IRQIndexMask)
|
||||||
{
|
{
|
||||||
|
#ifndef EXPERIMENTALZERO
|
||||||
IRQHandler* pHandler = IRQHandlers[IRQIndex];
|
IRQHandler* pHandler = IRQHandlers[IRQIndex];
|
||||||
|
|
||||||
if (pHandler != 0)
|
if (pHandler != 0)
|
||||||
(*pHandler)(Params[IRQIndex]);
|
(*pHandler)(Params[IRQIndex]);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
InterruptSystemDisableIRQ(IRQIndex);
|
InterruptSystemDisableIRQ(IRQIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ extern "C" {
|
||||||
#include "bcm2835int.h"
|
#include "bcm2835int.h"
|
||||||
|
|
||||||
#define EnableInterrupts() __asm volatile ("cpsie i")
|
#define EnableInterrupts() __asm volatile ("cpsie i")
|
||||||
#define DisableInterrupts() __asm volatile ("cpsid i")
|
#define DisableInterrupts() __asm volatile ("cpsid ifa, #0x13")
|
||||||
|
|
||||||
typedef void IRQHandler(void* param);
|
typedef void IRQHandler(void* param);
|
||||||
|
|
||||||
|
|
233
src/main.cpp
233
src/main.cpp
|
@ -101,7 +101,9 @@ u8 s_u8Memory[0xc000];
|
||||||
int numberOfUSBMassStorageDevices = 0;
|
int numberOfUSBMassStorageDevices = 0;
|
||||||
DiskCaddy diskCaddy;
|
DiskCaddy diskCaddy;
|
||||||
Pi1541 pi1541;
|
Pi1541 pi1541;
|
||||||
|
#if defined(PI1581SUPPORT)
|
||||||
Pi1581 pi1581;
|
Pi1581 pi1581;
|
||||||
|
#endif
|
||||||
CEMMCDevice m_EMMC;
|
CEMMCDevice m_EMMC;
|
||||||
Screen screen;
|
Screen screen;
|
||||||
ScreenLCD* screenLCD = 0;
|
ScreenLCD* screenLCD = 0;
|
||||||
|
@ -110,14 +112,17 @@ const char* fileBrowserSelectedName;
|
||||||
u8 deviceID = 8;
|
u8 deviceID = 8;
|
||||||
IEC_Commands m_IEC_Commands;
|
IEC_Commands m_IEC_Commands;
|
||||||
InputMappings* inputMappings;
|
InputMappings* inputMappings;
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
Keyboard* keyboard;
|
Keyboard* keyboard;
|
||||||
|
#endif
|
||||||
bool USBKeyboardDetected = false;
|
bool USBKeyboardDetected = false;
|
||||||
//bool resetWhileEmulating = false;
|
//bool resetWhileEmulating = false;
|
||||||
bool selectedViaIECCommands = false;
|
bool selectedViaIECCommands = false;
|
||||||
u16 pc;
|
u16 pc;
|
||||||
|
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
SpinLock core0RefreshingScreen;
|
SpinLock core0RefreshingScreen;
|
||||||
|
#endif
|
||||||
unsigned int screenWidth = 1024;
|
unsigned int screenWidth = 1024;
|
||||||
unsigned int screenHeight = 768;
|
unsigned int screenHeight = 768;
|
||||||
|
|
||||||
|
@ -225,8 +230,9 @@ void InitialiseHardware()
|
||||||
RPI_TouchInit();
|
RPI_TouchInit();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
screen.Open(screenWidth, screenHeight, 16);
|
screen.Open(screenWidth, screenHeight, 16);
|
||||||
|
#endif
|
||||||
RPI_PropertyInit();
|
RPI_PropertyInit();
|
||||||
RPI_PropertyAddTag(TAG_GET_MAX_CLOCK_RATE, ARM_CLK_ID);
|
RPI_PropertyAddTag(TAG_GET_MAX_CLOCK_RATE, ARM_CLK_ID);
|
||||||
RPI_PropertyProcess();
|
RPI_PropertyProcess();
|
||||||
|
@ -244,7 +250,6 @@ void InitialiseHardware()
|
||||||
|
|
||||||
void InitialiseLCD()
|
void InitialiseLCD()
|
||||||
{
|
{
|
||||||
|
|
||||||
FILINFO filLcdIcon;
|
FILINFO filLcdIcon;
|
||||||
|
|
||||||
int i2cBusMaster = options.I2CBusMaster();
|
int i2cBusMaster = options.I2CBusMaster();
|
||||||
|
@ -326,6 +331,7 @@ void InitialiseLCD()
|
||||||
// Care must be taken not to crowd out the shared cache with core1 as this could slow down core1 so that it no longer can perform its duties in the 1us timings it requires.
|
// Care must be taken not to crowd out the shared cache with core1 as this could slow down core1 so that it no longer can perform its duties in the 1us timings it requires.
|
||||||
void UpdateScreen()
|
void UpdateScreen()
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
bool oldLED = false;
|
bool oldLED = false;
|
||||||
bool oldMotor = false;
|
bool oldMotor = false;
|
||||||
bool oldATN = false;
|
bool oldATN = false;
|
||||||
|
@ -555,6 +561,7 @@ void UpdateScreen()
|
||||||
// Go back to sleep. The USB irq will wake us up again.
|
// Go back to sleep. The USB irq will wake us up again.
|
||||||
__asm ("WFE");
|
__asm ("WFE");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Snoop(u8 a)
|
static bool Snoop(u8 a)
|
||||||
|
@ -603,6 +610,7 @@ EmulatingMode BeginEmulating(FileBrowser* fileBrowser, const char* filenameForIc
|
||||||
DiskImage* diskImage = diskCaddy.SelectFirstImage();
|
DiskImage* diskImage = diskCaddy.SelectFirstImage();
|
||||||
if (diskImage)
|
if (diskImage)
|
||||||
{
|
{
|
||||||
|
#if defined(PI1581SUPPORT)
|
||||||
if (diskImage->IsD81())
|
if (diskImage->IsD81())
|
||||||
{
|
{
|
||||||
pi1581.Insert(diskImage);
|
pi1581.Insert(diskImage);
|
||||||
|
@ -611,6 +619,7 @@ EmulatingMode BeginEmulating(FileBrowser* fileBrowser, const char* filenameForIc
|
||||||
return EMULATING_1581;
|
return EMULATING_1581;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
pi1541.drive.Insert(diskImage);
|
pi1541.drive.Insert(diskImage);
|
||||||
fileBrowser->DisplayDiskInfo(diskImage, filenameForIcon);
|
fileBrowser->DisplayDiskInfo(diskImage, filenameForIcon);
|
||||||
|
@ -621,7 +630,7 @@ EmulatingMode BeginEmulating(FileBrowser* fileBrowser, const char* filenameForIc
|
||||||
inputMappings->WaitForClearButtons();
|
inputMappings->WaitForClearButtons();
|
||||||
return IEC_COMMANDS;
|
return IEC_COMMANDS;
|
||||||
}
|
}
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
static u32* dmaSound;
|
static u32* dmaSound;
|
||||||
|
|
||||||
struct DMA_ControlBlock
|
struct DMA_ControlBlock
|
||||||
|
@ -646,13 +655,15 @@ DMA_ControlBlock dmaSoundCB =
|
||||||
0,//&dmaSoundCB,
|
0,//&dmaSoundCB,
|
||||||
0, 0
|
0, 0
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
static void PlaySoundDMA()
|
static void PlaySoundDMA()
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
write32(PWM_DMAC, PWM_ENAB + 0x0001);
|
write32(PWM_DMAC, PWM_ENAB + 0x0001);
|
||||||
write32(DMA_ENABLE, 1); // DMA_EN0
|
write32(DMA_ENABLE, 1); // DMA_EN0
|
||||||
write32(DMA0_BASE + DMA_CONBLK_AD, (u32)&dmaSoundCB);
|
write32(DMA0_BASE + DMA_CONBLK_AD, (u32)&dmaSoundCB);
|
||||||
write32(DMA0_BASE + DMA_CS, DMA_ACTIVE);
|
write32(DMA0_BASE + DMA_CS, DMA_ACTIVE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalSetDeviceID(u8 id)
|
void GlobalSetDeviceID(u8 id)
|
||||||
|
@ -660,7 +671,9 @@ void GlobalSetDeviceID(u8 id)
|
||||||
deviceID = id;
|
deviceID = id;
|
||||||
m_IEC_Commands.SetDeviceId(id);
|
m_IEC_Commands.SetDeviceId(id);
|
||||||
pi1541.SetDeviceID(id);
|
pi1541.SetDeviceID(id);
|
||||||
|
#if defined(PI1581SUPPORT)
|
||||||
pi1581.SetDeviceID(id);
|
pi1581.SetDeviceID(id);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckAutoMountImage(EXIT_TYPE reset_reason , FileBrowser* fileBrowser)
|
void CheckAutoMountImage(EXIT_TYPE reset_reason , FileBrowser* fileBrowser)
|
||||||
|
@ -684,6 +697,156 @@ void CheckAutoMountImage(EXIT_TYPE reset_reason , FileBrowser* fileBrowser)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
EXIT_TYPE Emulate1541(FileBrowser* fileBrowser)
|
||||||
|
{
|
||||||
|
bool oldLED = false;
|
||||||
|
unsigned ctBefore = 0;
|
||||||
|
unsigned ctAfter = 0;
|
||||||
|
int cycleCount = 0;
|
||||||
|
unsigned caddyIndex;
|
||||||
|
int headSoundCounter = 0;
|
||||||
|
int headSoundFreqCounter = 0;
|
||||||
|
// const int headSoundFreq = 833; // 1200Hz = 1/1200 * 10^6;
|
||||||
|
const int headSoundFreq = 1000000 / options.SoundOnGPIOFreq(); // 1200Hz = 1/1200 * 10^6;
|
||||||
|
unsigned char oldHeadDir;
|
||||||
|
int resetCount = 0;
|
||||||
|
bool refreshOutsAfterCPUStep = true;
|
||||||
|
unsigned numberOfImages = diskCaddy.GetNumberOfImages();
|
||||||
|
unsigned numberOfImagesMax = numberOfImages;
|
||||||
|
if (numberOfImagesMax > 10)
|
||||||
|
numberOfImagesMax = 10;
|
||||||
|
|
||||||
|
diskCaddy.Display();
|
||||||
|
|
||||||
|
inputMappings->directDiskSwapRequest = 0;
|
||||||
|
// Force an update on all the buttons now before we start emulation mode.
|
||||||
|
IEC_Bus::ReadBrowseMode();
|
||||||
|
|
||||||
|
bool extraRAM = options.GetExtraRAM();
|
||||||
|
DataBusReadFn dataBusRead = extraRAM ? read6502ExtraRAM : read6502;
|
||||||
|
DataBusWriteFn dataBusWrite = extraRAM ? write6502ExtraRAM : write6502;
|
||||||
|
M6502& m6502 = pi1541.m6502;
|
||||||
|
m6502.SetBusFunctions(dataBusRead, dataBusWrite);
|
||||||
|
|
||||||
|
IEC_Bus::VIA = &pi1541.VIA[0];
|
||||||
|
IEC_Bus::port = pi1541.VIA[0].GetPortB();
|
||||||
|
pi1541.Reset(); // will call IEC_Bus::Reset();
|
||||||
|
IEC_Bus::OutputLED = false;
|
||||||
|
IEC_Bus::LetSRQBePulledHigh();
|
||||||
|
ctBefore = read32(ARM_SYSTIMER_CLO);
|
||||||
|
|
||||||
|
//resetWhileEmulating = false;
|
||||||
|
selectedViaIECCommands = false;
|
||||||
|
|
||||||
|
u32 hash = pi1541.drive.GetDiskImage()->GetHash();
|
||||||
|
// 0x42c02586 = maniac_mansion_s1[lucasfilm_1989](ntsc).g64
|
||||||
|
// 0x18651422 = aliens[electric_dreams_1987].g64
|
||||||
|
// 0x2a7f4b77 = zak_mckracken_boot[activision_1988](manual)(!).g64
|
||||||
|
if (hash == 0x42c02586 || hash == 0x18651422 || hash == 0x2a7f4b77)
|
||||||
|
{
|
||||||
|
refreshOutsAfterCPUStep = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (cycleCount < FAST_BOOT_CYCLES)
|
||||||
|
{
|
||||||
|
m6502.Step();
|
||||||
|
pi1541.Update();
|
||||||
|
cycleCount++;
|
||||||
|
IEC_Bus::ReadEmulationMode1541();
|
||||||
|
}
|
||||||
|
bool buttonState = false;
|
||||||
|
bool prevButtonState = false;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (m6502.SYNC()) // About to start a new instruction.
|
||||||
|
{
|
||||||
|
pc = m6502.GetPC();
|
||||||
|
// See if the emulated cpu is executing CD:_ (ie back out of emulated image)
|
||||||
|
if (snoopIndex == 0 && (pc == SNOOP_CD_CBM || pc == SNOOP_CD_JIFFY_BOTH || pc == SNOOP_CD_JIFFY_DRIVEONLY)) snoopPC = pc;
|
||||||
|
|
||||||
|
if (pc == snoopPC)
|
||||||
|
{
|
||||||
|
if (Snoop(m6502.GetA()))
|
||||||
|
{
|
||||||
|
return EXIT_CD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m6502.Step(); // If the CPU reads or writes to the VIA then clk and data can change
|
||||||
|
|
||||||
|
if (refreshOutsAfterCPUStep)
|
||||||
|
IEC_Bus::RefreshOuts1541(); // Now output all outputs.
|
||||||
|
|
||||||
|
IEC_Bus::OutputLED = pi1541.drive.IsLEDOn();
|
||||||
|
if (IEC_Bus::OutputLED ^ oldLED)
|
||||||
|
{
|
||||||
|
SetACTLed(IEC_Bus::OutputLED);
|
||||||
|
oldLED = IEC_Bus::OutputLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
pi1541.Update();
|
||||||
|
|
||||||
|
if (__builtin_expect(IEC_Bus::IsReset(), false))
|
||||||
|
resetCount++;
|
||||||
|
else
|
||||||
|
resetCount = 0;
|
||||||
|
|
||||||
|
if ((resetCount > 10))
|
||||||
|
{
|
||||||
|
return EXIT_RESET;
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonState = IEC_Bus::AnyButtonPressed();
|
||||||
|
if (__builtin_expect(buttonState, false))
|
||||||
|
{
|
||||||
|
IEC_Bus::ReadButtonsEmulationMode();
|
||||||
|
inputMappings->CheckButtonsEmulationMode();
|
||||||
|
if (numberOfImages > 1)
|
||||||
|
{
|
||||||
|
bool nextDisk = inputMappings->NextDisk();
|
||||||
|
bool prevDisk = inputMappings->PrevDisk();
|
||||||
|
if (nextDisk)
|
||||||
|
{
|
||||||
|
pi1541.drive.Insert(diskCaddy.PrevDisk());
|
||||||
|
}
|
||||||
|
if (prevDisk)
|
||||||
|
{
|
||||||
|
pi1541.drive.Insert(diskCaddy.NextDisk());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool exitEmulation = inputMappings->Exit();
|
||||||
|
if (exitEmulation)
|
||||||
|
return EXIT_KEYBOARD;
|
||||||
|
}
|
||||||
|
else if (__builtin_expect(!buttonState & prevButtonState, false))
|
||||||
|
{
|
||||||
|
IEC_Bus::ReadButtonsEmulationMode();
|
||||||
|
inputMappings->CheckButtonsEmulationMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
prevButtonState = buttonState;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ctAfter = read32(ARM_SYSTIMER_CLO);
|
||||||
|
} while (ctAfter == ctBefore); // Sync to the 1MHz clock
|
||||||
|
|
||||||
|
|
||||||
|
ctBefore = ctAfter;
|
||||||
|
IEC_Bus::ReadEmulationMode1541();
|
||||||
|
|
||||||
|
IEC_Bus::RefreshOuts1541(); // Now output all outputs.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
return EXIT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
EXIT_TYPE Emulate1541(FileBrowser* fileBrowser)
|
EXIT_TYPE Emulate1541(FileBrowser* fileBrowser)
|
||||||
{
|
{
|
||||||
EXIT_TYPE exitReason = EXIT_UNKNOWN;
|
EXIT_TYPE exitReason = EXIT_UNKNOWN;
|
||||||
|
@ -890,7 +1053,9 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser)
|
||||||
}
|
}
|
||||||
return exitReason;
|
return exitReason;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PI1581SUPPORT)
|
||||||
EXIT_TYPE Emulate1581(FileBrowser* fileBrowser)
|
EXIT_TYPE Emulate1581(FileBrowser* fileBrowser)
|
||||||
{
|
{
|
||||||
EXIT_TYPE exitReason = EXIT_UNKNOWN;
|
EXIT_TYPE exitReason = EXIT_UNKNOWN;
|
||||||
|
@ -1075,10 +1240,13 @@ EXIT_TYPE Emulate1581(FileBrowser* fileBrowser)
|
||||||
}
|
}
|
||||||
return exitReason;
|
return exitReason;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void emulator()
|
void emulator()
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
Keyboard* keyboard = Keyboard::Instance();
|
Keyboard* keyboard = Keyboard::Instance();
|
||||||
|
#endif
|
||||||
FileBrowser* fileBrowser;
|
FileBrowser* fileBrowser;
|
||||||
EXIT_TYPE exitReason = EXIT_UNKNOWN;
|
EXIT_TYPE exitReason = EXIT_UNKNOWN;
|
||||||
|
|
||||||
|
@ -1095,7 +1263,6 @@ void emulator()
|
||||||
m_IEC_Commands.SetNewDiskType(options.GetNewDiskType());
|
m_IEC_Commands.SetNewDiskType(options.GetNewDiskType());
|
||||||
|
|
||||||
emulating = IEC_COMMANDS;
|
emulating = IEC_COMMANDS;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (emulating == IEC_COMMANDS)
|
if (emulating == IEC_COMMANDS)
|
||||||
|
@ -1107,8 +1274,9 @@ void emulator()
|
||||||
IEC_Bus::Reset();
|
IEC_Bus::Reset();
|
||||||
|
|
||||||
IEC_Bus::LetSRQBePulledHigh();
|
IEC_Bus::LetSRQBePulledHigh();
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
core0RefreshingScreen.Acquire();
|
core0RefreshingScreen.Acquire();
|
||||||
|
#endif
|
||||||
IEC_Bus::WaitMicroSeconds(100);
|
IEC_Bus::WaitMicroSeconds(100);
|
||||||
|
|
||||||
roms.ResetCurrentROMIndex();
|
roms.ResetCurrentROMIndex();
|
||||||
|
@ -1118,14 +1286,15 @@ void emulator()
|
||||||
fileBrowser->ClearSelections();
|
fileBrowser->ClearSelections();
|
||||||
|
|
||||||
fileBrowser->RefeshDisplay(); // Just redisplay the current folder.
|
fileBrowser->RefeshDisplay(); // Just redisplay the current folder.
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
core0RefreshingScreen.Release();
|
core0RefreshingScreen.Release();
|
||||||
|
#endif
|
||||||
selectedViaIECCommands = false;
|
selectedViaIECCommands = false;
|
||||||
|
|
||||||
inputMappings->Reset();
|
inputMappings->Reset();
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
inputMappings->SetKeyboardBrowseLCDScreen(screenLCD && options.KeyboardBrowseLCDScreen());
|
inputMappings->SetKeyboardBrowseLCDScreen(screenLCD && options.KeyboardBrowseLCDScreen());
|
||||||
|
#endif
|
||||||
fileBrowser->ShowDeviceAndROM();
|
fileBrowser->ShowDeviceAndROM();
|
||||||
|
|
||||||
if (!options.GetDisableSD2IECCommands())
|
if (!options.GetDisableSD2IECCommands())
|
||||||
|
@ -1149,7 +1318,6 @@ void emulator()
|
||||||
break;
|
break;
|
||||||
case IEC_Commands::NONE:
|
case IEC_Commands::NONE:
|
||||||
fileBrowser->Update();
|
fileBrowser->Update();
|
||||||
|
|
||||||
// Check selections made via FileBrowser
|
// Check selections made via FileBrowser
|
||||||
if (fileBrowser->SelectionsMade())
|
if (fileBrowser->SelectionsMade())
|
||||||
emulating = BeginEmulating(fileBrowser, fileBrowser->LastSelectionName());
|
emulating = BeginEmulating(fileBrowser, fileBrowser->LastSelectionName());
|
||||||
|
@ -1210,7 +1378,7 @@ void emulator()
|
||||||
fileBrowser->ShowDeviceAndROM();
|
fileBrowser->ShowDeviceAndROM();
|
||||||
break;
|
break;
|
||||||
case IEC_Commands::DEVICE_SWITCHED:
|
case IEC_Commands::DEVICE_SWITCHED:
|
||||||
DEBUG_LOG("DEVICE_SWITCHED\r\n");
|
DEBUG_LOG("DECIVE_SWITCHED\r\n");
|
||||||
fileBrowser->DeviceSwitched();
|
fileBrowser->DeviceSwitched();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1234,8 +1402,10 @@ void emulator()
|
||||||
{
|
{
|
||||||
if (emulating == EMULATING_1541)
|
if (emulating == EMULATING_1541)
|
||||||
exitReason = Emulate1541(fileBrowser);
|
exitReason = Emulate1541(fileBrowser);
|
||||||
|
#if defined(PI1581SUPPORT)
|
||||||
else
|
else
|
||||||
exitReason = Emulate1581(fileBrowser);
|
exitReason = Emulate1581(fileBrowser);
|
||||||
|
#endif
|
||||||
|
|
||||||
DEBUG_LOG("Exited emulation\r\n");
|
DEBUG_LOG("Exited emulation\r\n");
|
||||||
|
|
||||||
|
@ -1320,6 +1490,7 @@ static bool AttemptToLoadROM(char* ROMName)
|
||||||
|
|
||||||
static void DisplayLogo()
|
static void DisplayLogo()
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
int w;
|
int w;
|
||||||
int h;
|
int h;
|
||||||
int channels_in_file;
|
int channels_in_file;
|
||||||
|
@ -1329,6 +1500,7 @@ static void DisplayLogo()
|
||||||
|
|
||||||
snprintf(tempBuffer, tempBufferSize, "V%d.%02d", versionMajor, versionMinor);
|
snprintf(tempBuffer, tempBufferSize, "V%d.%02d", versionMajor, versionMinor);
|
||||||
screen.PrintText(false, 20, 180, tempBuffer, FileBrowser::Colour(VIC2_COLOUR_INDEX_BLUE));
|
screen.PrintText(false, 20, 180, tempBuffer, FileBrowser::Colour(VIC2_COLOUR_INDEX_BLUE));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LoadOptions()
|
static void LoadOptions()
|
||||||
|
@ -1354,6 +1526,7 @@ static void LoadOptions()
|
||||||
|
|
||||||
void DisplayOptions(int y_pos)
|
void DisplayOptions(int y_pos)
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
// print confirmation of parsed options
|
// print confirmation of parsed options
|
||||||
snprintf(tempBuffer, tempBufferSize, "ignoreReset = %d\r\n", options.IgnoreReset());
|
snprintf(tempBuffer, tempBufferSize, "ignoreReset = %d\r\n", options.IgnoreReset());
|
||||||
screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK);
|
screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK);
|
||||||
|
@ -1375,10 +1548,12 @@ void DisplayOptions(int y_pos)
|
||||||
screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK);
|
screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK);
|
||||||
snprintf(tempBuffer, tempBufferSize, "AutoBaseName = %s\r\n", options.GetAutoBaseName());
|
snprintf(tempBuffer, tempBufferSize, "AutoBaseName = %s\r\n", options.GetAutoBaseName());
|
||||||
screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK);
|
screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayI2CScan(int y_pos)
|
void DisplayI2CScan(int y_pos)
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
int BSCMaster = options.I2CBusMaster();
|
int BSCMaster = options.I2CBusMaster();
|
||||||
|
|
||||||
snprintf(tempBuffer, tempBufferSize, "Scanning i2c bus %d ...\r\n", BSCMaster);
|
snprintf(tempBuffer, tempBufferSize, "Scanning i2c bus %d ...\r\n", BSCMaster);
|
||||||
|
@ -1401,6 +1576,7 @@ void DisplayI2CScan(int y_pos)
|
||||||
ptr += snprintf (tempBuffer+ptr, tempBufferSize-ptr, "Nothing");
|
ptr += snprintf (tempBuffer+ptr, tempBufferSize-ptr, "Nothing");
|
||||||
|
|
||||||
screen.PrintText(false, 0, y_pos+16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK);
|
screen.PrintText(false, 0, y_pos+16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CheckOptions()
|
static void CheckOptions()
|
||||||
|
@ -1415,7 +1591,7 @@ static void CheckOptions()
|
||||||
|
|
||||||
deviceID = (u8)options.GetDeviceID();
|
deviceID = (u8)options.GetDeviceID();
|
||||||
DEBUG_LOG("DeviceID = %d\r\n", deviceID);
|
DEBUG_LOG("DeviceID = %d\r\n", deviceID);
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
const char* FontROMName = options.GetRomFontName();
|
const char* FontROMName = options.GetRomFontName();
|
||||||
if (FontROMName)
|
if (FontROMName)
|
||||||
{
|
{
|
||||||
|
@ -1450,7 +1626,7 @@ static void CheckOptions()
|
||||||
//DEBUG_LOG("Read ROM %s from options\r\n", ROMName);
|
//DEBUG_LOG("Read ROM %s from options\r\n", ROMName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
const char* ROMName1581 = options.GetRomName1581();
|
const char* ROMName1581 = options.GetRomName1581();
|
||||||
if (ROMName1581)
|
if (ROMName1581)
|
||||||
{
|
{
|
||||||
|
@ -1522,6 +1698,7 @@ static void CheckOptions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (roms.ROMValid[0] == false && !(AttemptToLoadROM("d1541.rom") || AttemptToLoadROM("dos1541") || AttemptToLoadROM("d1541II") || AttemptToLoadROM("Jiffy.bin")))
|
if (roms.ROMValid[0] == false && !(AttemptToLoadROM("d1541.rom") || AttemptToLoadROM("dos1541") || AttemptToLoadROM("d1541II") || AttemptToLoadROM("Jiffy.bin")))
|
||||||
{
|
{
|
||||||
snprintf(tempBuffer, tempBufferSize, "No ROM file found!\r\nPlease copy a valid 1541 ROM file in the root folder of the SD card.\r\nThe file needs to be called 'dos1541'.");
|
snprintf(tempBuffer, tempBufferSize, "No ROM file found!\r\nPlease copy a valid 1541 ROM file in the root folder of the SD card.\r\nThe file needs to be called 'dos1541'.");
|
||||||
|
@ -1563,6 +1740,7 @@ bool SwitchDrive(const char* drive)
|
||||||
|
|
||||||
void UpdateFirmwareToSD()
|
void UpdateFirmwareToSD()
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
const char* firmwareName = "kernel.img";
|
const char* firmwareName = "kernel.img";
|
||||||
DIR dir;
|
DIR dir;
|
||||||
FILINFO filInfo;
|
FILINFO filInfo;
|
||||||
|
@ -1658,10 +1836,12 @@ void UpdateFirmwareToSD()
|
||||||
f_chdir(cwd);
|
f_chdir(cwd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayMessage(int x, int y, bool LCD, const char* message, u32 textColour, u32 backgroundColour)
|
void DisplayMessage(int x, int y, bool LCD, const char* message, u32 textColour, u32 backgroundColour)
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
char buffer[256] = { 0 };
|
char buffer[256] = { 0 };
|
||||||
|
|
||||||
if (!LCD)
|
if (!LCD)
|
||||||
|
@ -1682,8 +1862,15 @@ void DisplayMessage(int x, int y, bool LCD, const char* message, u32 textColour,
|
||||||
screenLCD->SwapBuffers();
|
screenLCD->SwapBuffers();
|
||||||
|
|
||||||
core0RefreshingScreen.Release();
|
core0RefreshingScreen.Release();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
RGBA BkColour = RGBA(0, 0, 0, 0xFF);
|
||||||
|
|
||||||
|
screenLCD->Clear(BkColour);
|
||||||
|
screenLCD->PrintText(false, x, y, (char*)message, textColour, backgroundColour);
|
||||||
|
screenLCD->SwapBuffers();
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@ -1699,8 +1886,9 @@ extern "C"
|
||||||
disk_setEMM(&m_EMMC);
|
disk_setEMM(&m_EMMC);
|
||||||
f_mount(&fileSystemSD, "SD:", 1);
|
f_mount(&fileSystemSD, "SD:", 1);
|
||||||
|
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
RPI_AuxMiniUartInit(115200, 8);
|
RPI_AuxMiniUartInit(115200, 8);
|
||||||
|
#endif
|
||||||
LoadOptions();
|
LoadOptions();
|
||||||
|
|
||||||
InitialiseHardware();
|
InitialiseHardware();
|
||||||
|
@ -1712,7 +1900,7 @@ extern "C"
|
||||||
DisplayLogo();
|
DisplayLogo();
|
||||||
|
|
||||||
InitialiseLCD();
|
InitialiseLCD();
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
int y_pos = 184;
|
int y_pos = 184;
|
||||||
snprintf(tempBuffer, tempBufferSize, "Copyright(C) 2018 Stephen White");
|
snprintf(tempBuffer, tempBufferSize, "Copyright(C) 2018 Stephen White");
|
||||||
screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK);
|
screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK);
|
||||||
|
@ -1727,10 +1915,12 @@ extern "C"
|
||||||
if (options.ShowOptions())
|
if (options.ShowOptions())
|
||||||
DisplayOptions(y_pos+=32);
|
DisplayOptions(y_pos+=32);
|
||||||
|
|
||||||
|
#endif
|
||||||
//if (!options.QuickBoot())
|
//if (!options.QuickBoot())
|
||||||
// IEC_Bus::WaitMicroSeconds(3 * 1000000);
|
//IEC_Bus::WaitMicroSeconds(3 * 1000000);
|
||||||
|
|
||||||
InterruptSystemInitialize();
|
InterruptSystemInitialize();
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
TimerSystemInitialize();
|
TimerSystemInitialize();
|
||||||
|
|
||||||
USPiInitialize();
|
USPiInitialize();
|
||||||
|
@ -1752,6 +1942,7 @@ extern "C"
|
||||||
// DEBUG_LOG("Mouse found\r\n");
|
// DEBUG_LOG("Mouse found\r\n");
|
||||||
|
|
||||||
keyboard = new Keyboard();
|
keyboard = new Keyboard();
|
||||||
|
#endif
|
||||||
inputMappings = new InputMappings();
|
inputMappings = new InputMappings();
|
||||||
//USPiMouseRegisterStatusHandler(MouseHandler);
|
//USPiMouseRegisterStatusHandler(MouseHandler);
|
||||||
|
|
||||||
|
@ -1762,7 +1953,7 @@ extern "C"
|
||||||
IEC_Bus::SetInvertIECInputs(options.InvertIECInputs());
|
IEC_Bus::SetInvertIECInputs(options.InvertIECInputs());
|
||||||
IEC_Bus::SetInvertIECOutputs(options.InvertIECOutputs());
|
IEC_Bus::SetInvertIECOutputs(options.InvertIECOutputs());
|
||||||
IEC_Bus::SetIgnoreReset(options.IgnoreReset());
|
IEC_Bus::SetIgnoreReset(options.IgnoreReset());
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
if (!options.SoundOnGPIO())
|
if (!options.SoundOnGPIO())
|
||||||
{
|
{
|
||||||
dmaSound = (u32*)malloc(Sample_bin_size * 4);
|
dmaSound = (u32*)malloc(Sample_bin_size * 4);
|
||||||
|
@ -1786,7 +1977,7 @@ extern "C"
|
||||||
if (SwitchDrive("USB01:"))
|
if (SwitchDrive("USB01:"))
|
||||||
UpdateFirmwareToSD();
|
UpdateFirmwareToSD();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
f_chdir("/1541");
|
f_chdir("/1541");
|
||||||
|
|
||||||
m_IEC_Commands.SetStarFileName(options.GetStarFileName());
|
m_IEC_Commands.SetStarFileName(options.GetStarFileName());
|
||||||
|
@ -1795,9 +1986,7 @@ extern "C"
|
||||||
|
|
||||||
pi1541.drive.SetVIA(&pi1541.VIA[1]);
|
pi1541.drive.SetVIA(&pi1541.VIA[1]);
|
||||||
pi1541.VIA[0].GetPortB()->SetPortOut(0, IEC_Bus::PortB_OnPortOut);
|
pi1541.VIA[0].GetPortB()->SetPortOut(0, IEC_Bus::PortB_OnPortOut);
|
||||||
|
|
||||||
IEC_Bus::Initialise();
|
IEC_Bus::Initialise();
|
||||||
|
|
||||||
if (screenLCD)
|
if (screenLCD)
|
||||||
screenLCD->ClearInit(0);
|
screenLCD->ClearInit(0);
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,11 @@ public:
|
||||||
inline unsigned int QuickBoot() const { return quickBoot; }
|
inline unsigned int QuickBoot() const { return quickBoot; }
|
||||||
inline unsigned int ShowOptions() const { return showOptions; }
|
inline unsigned int ShowOptions() const { return showOptions; }
|
||||||
inline unsigned int DisplayPNGIcons() const { return displayPNGIcons; }
|
inline unsigned int DisplayPNGIcons() const { return displayPNGIcons; }
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
inline unsigned int SoundOnGPIO() const { return false; }
|
||||||
|
#else
|
||||||
inline unsigned int SoundOnGPIO() const { return soundOnGPIO; }
|
inline unsigned int SoundOnGPIO() const { return soundOnGPIO; }
|
||||||
|
#endif
|
||||||
inline unsigned int SoundOnGPIODuration() const { return soundOnGPIODuration; }
|
inline unsigned int SoundOnGPIODuration() const { return soundOnGPIODuration; }
|
||||||
inline unsigned int SoundOnGPIOFreq() const { return soundOnGPIOFreq; }
|
inline unsigned int SoundOnGPIOFreq() const { return soundOnGPIOFreq; }
|
||||||
inline unsigned int SplitIECLines() const { return splitIECLines; }
|
inline unsigned int SplitIECLines() const { return splitIECLines; }
|
||||||
|
|
Loading…
Reference in a new issue