Added Mac II ROMDisk driver stuff

This commit is contained in:
Zane Kaminski 2020-08-11 14:57:00 -04:00
parent f55793a356
commit 49b479949a
5 changed files with 642 additions and 0 deletions

102
Makefile Normal file
View File

@ -0,0 +1,102 @@
# path to RETRO68
RETRO68=/Users/zane/Retro68-build/toolchain
PREFIX=$(RETRO68)/m68k-apple-macos
AS=$(RETRO68)/bin/m68k-apple-macos-as
CC=$(RETRO68)/bin/m68k-apple-macos-gcc
LD=$(RETRO68)/bin/m68k-apple-macos-ld
OBJCOPY=$(RETRO68)/bin/m68k-apple-macos-objcopy
OBJDUMP=$(RETRO68)/bin/m68k-apple-macos-objdump
all: bin/rom16M_swap.bin obj/rdisk1M5.s obj/rdisk7M5.s obj/driver1M5.s obj/driver7M5.s obj/entry_rel.sym obj/driver_abs.sym
obj:
mkdir obj
bin:
mkdir bin
obj/entry.o: entry.s obj
$(AS) $< -o $@
obj/entry_rel.sym: obj obj/entry.o
$(OBJDUMP) -t obj/entry.o > $@
obj/rdisk1M5.o: rdisk.c obj
$(CC) -DRDiskSize=1572864 -c -Os $< -o $@
obj/rdisk7M5.o: rdisk.c obj
$(CC) -DRDiskSize=7864320 -c -Os $< -o $@
obj/rdisk1M5.s: obj obj/rdisk1M5.o
$(OBJDUMP) -d obj/rdisk1M5.o > $@
obj/rdisk7M5.s: obj obj/rdisk7M5.o
$(OBJDUMP) -d obj/rdisk1M5.o > $@
obj/driver1M5.o: obj obj/entry.o obj/rdisk1M5.o
$(LD) -Ttext=40851D70 -o $@ obj/entry.o obj/rdisk1M5.o
obj/driver7M5.o: obj obj/entry.o obj/rdisk7M5.o
$(LD) -Ttext=40851D70 -o $@ obj/entry.o obj/rdisk7M5.o
obj/driver1M5.s: obj obj/driver1M5.o
$(OBJDUMP) -d obj/driver1M5.o > $@
obj/driver7M5.s: obj obj/driver7M5.o
$(OBJDUMP) -d obj/driver7M5.o > $@
obj/driver_abs.sym: obj obj/driver1M5.o
$(OBJDUMP) -t obj/driver1M5.o > $@
bin/driver1M5.bin: bin obj/driver1M5.o
$(OBJCOPY) -O binary obj/driver1M5.o $@
bin/driver7M5.bin: bin obj/driver7M5.o
$(OBJCOPY) -O binary obj/driver7M5.o $@
bin/rom2M.bin: baserom.bin RDisk1M5.dsk bin bin/driver1M5.bin obj/driver_abs.sym obj/entry_rel.sym
cp baserom.bin $@ # Copy base rom
# Patch driver
dd if=bin/driver1M5.bin of=$@ bs=1 seek=335248 skip=32 conv=notrunc # Copy driver code
printf '\x78' | dd of=$@ bs=1 seek=335168 count=1 conv=notrunc # Set resource flags
printf '\x4F' | dd of=$@ bs=1 seek=335216 count=1 conv=notrunc # Set driver flags
cat obj/entry_rel.sym | grep "DOpen" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335224 count=2 conv=notrunc
cat obj/entry_rel.sym | grep "DPrime" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335226 count=2 conv=notrunc
cat obj/entry_rel.sym | grep "DControl" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335228 count=2 conv=notrunc
cat obj/entry_rel.sym | grep "DStatus" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335230 count=2 conv=notrunc
cat obj/entry_rel.sym | grep "DClose" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335232 count=2 conv=notrunc
dd if=RDisk1M5.dsk of=$@ bs=1024 seek=512 count=1536 conv=notrunc # copy disk image
bin/rom8M.bin: baserom.bin RDisk7M5.dsk bin bin/driver7M5.bin obj/driver_abs.sym obj/entry_rel.sym
cp baserom.bin $@ # Copy base rom
# Patch driver
dd if=bin/driver7M5.bin of=$@ bs=1 seek=335248 skip=32 conv=notrunc # Copy driver code
printf '\x78' | dd of=$@ bs=1 seek=335168 count=1 conv=notrunc # Set resource flags
printf '\x4F' | dd of=$@ bs=1 seek=335216 count=1 conv=notrunc # Set driver flags
cat obj/entry_rel.sym | grep "DOpen" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335224 count=2 conv=notrunc
cat obj/entry_rel.sym | grep "DPrime" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335226 count=2 conv=notrunc
cat obj/entry_rel.sym | grep "DControl" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335228 count=2 conv=notrunc
cat obj/entry_rel.sym | grep "DStatus" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335230 count=2 conv=notrunc
cat obj/entry_rel.sym | grep "DClose" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335232 count=2 conv=notrunc
dd if=RDisk7M5.dsk of=$@ bs=1024 seek=512 count=7680 conv=notrunc # copy disk image
bin/rom8M_swap.bin: bin/rom8M.bin
dd if=bin/rom8M.bin of=$@ conv=swab # swap bytes
bin/rom2M_swap.bin: bin/rom2M.bin
dd if=bin/rom2M.bin of=$@ conv=swab # swap bytes
bin/rom16M_swap.bin: bin/rom2M_swap.bin bin/rom8M_swap.bin
cat bin/rom8M_swap.bin > $@
cat bin/rom2M_swap.bin >> $@
.PHONY: clean
clean:
rm -fr bin obj

BIN
baserom.bin Executable file

Binary file not shown.

60
entry.s Normal file
View File

@ -0,0 +1,60 @@
.EQU killCode, 1
.EQU noQueueBit, 9
.EQU kioTrap, 6
.EQU kioResult, 16
.EQU kcsCode, 26
.EQU JIODone, 0x08FC
dc.l 0x00000000, 0x00000000, 0x00000000, 0x00000000
dc.l 0x00000000, 0x00000000, 0x00000000, 0x00000000
.ascii "\5RDisk\0"
.align 4
DOpen:
movem.l %A0-%A1, -(%SP)
bsr RDiskOpen
movem.l (%SP)+, %A0-%A1
rts
DClose:
movem.l %A0-%A1, -(%SP)
bsr RDiskClose
movem.l (%SP)+, %A0-%A1
rts
DPrime:
movem.l %A0-%A1, -(%SP)
bsr RDiskPrime
movem.l (%SP)+, %A0-%A1
bra.b IOReturn
DControl:
movem.l %A0-%A1, -(%SP)
bsr RDiskControl
movem.l (%SP)+, %A0-%A1
cmpi.w #killCode, kcsCode(%A0)
bne.b IOReturn
rts
DStatus:
movem.l %A0-%A1, -(%SP)
bsr RDiskStatus
movem.l (%SP)+, %A0-%A1
IOReturn:
move.w kioTrap(%A0), %D1
btst #noQueueBit, %D1
beq.b Queued
NotQueued:
tst.w %D0
ble.b ImmedRTS
clr.w %D0
ImmedRTS:
move.w %D0, kioResult(%A0)
rts
Queued:
move.l JIODone, -(%SP)
rts

285
rdisk.c Normal file
View File

@ -0,0 +1,285 @@
#include <Memory.h>
#include <Devices.h>
#include <Files.h>
#include <Disks.h>
#include <Errors.h>
#include <Events.h>
#include <OSUtils.h>
#include "rdisk.h"
// Decode keyboard/PRAM settings
static void RDiskDecodeSettings(RDiskStorage_t *c, Ptr unmount, Ptr mount, Ptr ram) {
// Decode settings
if (RDiskIsRPressed()) { // R boots from ROM disk
*unmount = 0; // Don't unmount so we boot from this drive
*mount = 0; // No need to mount later since we are boot disk
*ram = RDiskIsAPressed(); // A enables RAM disk
} else {
// Read PRAM
char legacy_startup, legacy_ram;
RDiskReadXPRAM(1, 4, &legacy_startup);
RDiskReadXPRAM(1, 5, &legacy_ram);
if (legacy_startup & 1) { // Boot from ROM disk
*unmount = 0; // Don't unmount so we boot from this drive
*mount = 0; // No need to mount later since we are boot disk
*ram = legacy_ram & 1;
} else if (legacy_startup & 2) { // Mount ROM disk
*unmount = 1; // Unmount to not boot from our disk
*mount = 1; // Mount in accRun
*ram = legacy_ram & 1;
} else {
*unmount = 1; // Unmount
*mount = 0; // Don't mount again
*ram = 0; // Don't allocate RAM disk
}
}
}
// Switch to 32-bit mode and copy
#pragma parameter RDiskCopy24(__A0, __A1, __D0)
void RDiskCopy24(Ptr sourcePtr, Ptr destPtr, unsigned long byteCount) {
char mode = true32b;
SwapMMUMode(&mode);
BlockMove(sourcePtr, destPtr, byteCount);
SwapMMUMode(&mode);
}
// Figure out the first available drive number >= 5
static int RDiskFindDrvNum() {
DrvQElPtr dq;
int drvNum = 5;
for (dq = (DrvQElPtr)(GetDrvQHdr())->qHead; dq; dq = (DrvQElPtr)dq->qLink) {
if (dq->dQDrive >= drvNum) { drvNum = dq->dQDrive + 1; }
}
return drvNum;
}
#pragma parameter __D0 RDiskOpen(__A0, __A1)
OSErr RDiskOpen(IOParamPtr p, DCtlPtr d) {
int drvNum;
RDiskStorage_t *c;
char legacy_startup, legacy_ram;
// Do nothing if already opened
if (d->dCtlStorage) { return noErr; }
// Do nothing if inhibited
RDiskReadXPRAM(1, 4, &legacy_startup);
RDiskReadXPRAM(1, 5, &legacy_ram);
if ((legacy_startup & 0x07) == 0x04) { return noErr; }
// Allocate storage struct
d->dCtlStorage = NewHandleSysClear(sizeof(RDiskStorage_t));
if (!d->dCtlStorage) { return openErr; }
// Lock our storage struct and get master pointer
HLock(d->dCtlStorage);
c = *(RDiskStorage_t**)d->dCtlStorage;
// Find first available drive number
drvNum = RDiskFindDrvNum();
// Set drive status
//c->status.track = 0;
c->status.writeProt = -1; // nonzero is write protected
c->status.diskInPlace = 8; // 8 is nonejectable disk
c->status.installed = 1; // drive installed
//c->status.sides = 0;
//c->status.qType = 1;
c->status.dQDrive = drvNum;
//c->status.dQFSID = 0;
c->status.dQRefNum = d->dCtlRefNum;
c->status.driveSize = RDiskSize / 512;
//c->status.driveS1 = (RDiskSize / 512) >> 16;
// Decompress icon
#ifdef RDISK_COMPRESS_ICON_ENABLE
char *src = &RDiskIconCompressed[0];
char *dst = &c->icon[0];
UnpackBits(&src, &dst, RDISK_ICON_SIZE);
#endif
// Add drive to drive queue and return
RDiskAddDrive(c->status.dQRefNum, drvNum, (DrvQElPtr)&c->status.qLink);
return noErr;
}
// Init is called at beginning of first prime (read/write) call
static void RDiskInit(IOParamPtr p, DCtlPtr d, RDiskStorage_t *c) {
char unmountEN, mountEN, ramEN;
// Mark init done
c->initialized = 1;
// Decode settings
RDiskDecodeSettings(c, &unmountEN, &mountEN, &ramEN);
// If RAM disk enabled, try to allocate RAM disk buffer if not already
if (ramEN & !c->ramdisk) {
if (*MMU32bit) { // 32-bit mode
unsigned long minBufPtr, newBufPtr;
// Compute if there is enough high memory
minBufPtr = ((unsigned long)*MemTop / 2) + 1024;
newBufPtr = (unsigned long)*BufPtr - RDiskSize;
if (newBufPtr > minBufPtr && (unsigned long)*BufPtr > newBufPtr) {
// Allocate RAM disk buffer by lowering BufPtr
*BufPtr = (Ptr)newBufPtr;
// Set RAM disk buffer pointer.
c->ramdisk = *BufPtr;
// Copy ROM disk image to RAM disk
BlockMove(RDiskBuf, c->ramdisk, RDiskSize);
// Clearing write protect marks RAM disk enabled
c->status.writeProt = 0;
}
} else { // 24-bit mode
// Put RAM disk just past 8MB
c->ramdisk = (Ptr)(8 * 1024 * 1024);
// Copy ROM disk image to RAM disk
copy24(RDiskBuf, c->ramdisk, RDiskSize);
// Clearing write protect marks RAM disk enabled
c->status.writeProt = 0;
//FIXME: what if we don't have enough RAM?
// Will this wrap around and overwrite low memory?
// That's not the worst, since the system would just crash,
// but it would be better to switch to read-only status
}
}
// Unmount if not booting from ROM disk
if (unmountEN) { c->status.diskInPlace = 0; }
// If mount enabled, enable accRun to post disk inserted event later
if (mountEN) {
d->dCtlDelay = 150; // Set accRun delay (150 ticks is 2.5 sec.)
d->dCtlFlags |= dNeedTimeMask; // Enable accRun
}
}
#pragma parameter __D0 RDiskPrime(__A0, __A1)
OSErr RDiskPrime(IOParamPtr p, DCtlPtr d) {
RDiskStorage_t *c;
char cmd;
Ptr disk;
// Return disk offline error if dCtlStorage null
if (!d->dCtlStorage) { return notOpenErr; }
// Dereference dCtlStorage to get pointer to our context
c = *(RDiskStorage_t**)d->dCtlStorage;
// Initialize if this is the first prime call
if (!c->initialized) { RDiskInit(p, d, c); }
// Return disk offline error if virtual disk not inserted
if (!c->status.diskInPlace) { return offLinErr; }
// Get pointer to RAM or ROM disk buffer
disk = (c->ramdisk ? c->ramdisk : RDiskBuf) + d->dCtlPosition;
// Bounds checking
if (d->dCtlPosition >= RDiskSize || p->ioReqCount >= RDiskSize ||
d->dCtlPosition + p->ioReqCount >= RDiskSize) { return paramErr; }
// Service read or write request
cmd = p->ioTrap & 0x00FF;
if (cmd == aRdCmd) { // Read
// Read from disk into buffer.
if (*MMU32bit) { BlockMove(disk, p->ioBuffer, p->ioReqCount); }
else { copy24(disk, StripAddress(p->ioBuffer), p->ioReqCount); }
} else if (cmd == aWrCmd) { // Write
// Fail if write protected or RAM disk buffer not set up
if (c->status.writeProt || !c->ramdisk) { return wPrErr; }
// Write from buffer into disk.
if (*MMU32bit) { BlockMove(p->ioBuffer, disk, p->ioReqCount); }
else { copy24(StripAddress(p->ioBuffer), disk, p->ioReqCount); }
} else { return noErr; } //FIXME: Fail if cmd isn't read or write?
// Update count and position/offset, then return
d->dCtlPosition += p->ioReqCount;
p->ioActCount = p->ioReqCount;
return noErr;
}
#pragma parameter __D0 RDiskControl(__A0, __A1)
OSErr RDiskControl(CntrlParamPtr p, DCtlPtr d) {
RDiskStorage_t *c;
// Fail if dCtlStorage null
if (!d->dCtlStorage) { return notOpenErr; }
// Dereference dCtlStorage to get pointer to our context
c = *(RDiskStorage_t**)d->dCtlStorage;
// Handle control request based on csCode
switch (p->csCode) {
case killCode:
return noErr;
case kFormat:
if (!c->status.diskInPlace || c->status.writeProt ||
!c->ramdisk) { return controlErr; }
long zero[32];
for (int i = 0; i < 32; i++) { zero[i] = 0; }
for (int i = 0; i < 32; i++) {
copy24((Ptr)zero, c->ramdisk + i * sizeof(zero), sizeof(zero));
}
return noErr;
case kVerify:
if (!c->status.diskInPlace) { return controlErr; }
return noErr;
case kEject:
// "Reinsert" disk if ejected illegally
if (c->status.diskInPlace) {
PostEvent(diskEvt, c->status.dQDrive);
}
return controlErr; // Eject not allowed so return error
case accRun:
d->dCtlFlags &= ~dNeedTimeMask; // Disable accRun
c->status.diskInPlace = 8; // 8 is nonejectable disk
PostEvent(diskEvt, c->status.dQDrive); // Post disk inserted event
return noErr;
case kDriveIcon: case kMediaIcon: // Get icon
#ifdef RDISK_COMPRESS_ICON_ENABLE
*(Ptr*)p->csParam = (Ptr)c->icon;
#else
*(Ptr*)p->csParam = (Ptr)RDiskIcon;
#endif
return noErr;
case kDriveInfo:
// high word (bytes 2 & 3) clear
// byte 1 = primary + fixed media + internal
// byte 0 = drive type (0x10 is RAM disk) / (0x11 is ROM disk)
if (c->status.writeProt) { *(long*)p->csParam = 0x00000410; }
else { *(long*)p->csParam = 0x00000411; }
return noErr;
case 24: // Return SCSI partition size
*(long*)p->csParam = RDiskSize / 512;
return noErr;
case 2351: // Post-boot
c->initialized = 1; // Skip initialization
d->dCtlDelay = 30; // Set accRun delay (30 ticks is 0.5 sec.)
d->dCtlFlags |= dNeedTimeMask; // Enable accRun
return noErr;
default: return controlErr;
}
}
#pragma parameter __D0 RDiskStatus(__A0, __A1)
OSErr RDiskStatus(CntrlParamPtr p, DCtlPtr d) {
RDiskStorage_t *c;
// Fail if dCtlStorage null
if (!d->dCtlStorage) { return notOpenErr; }
// Dereference dCtlStorage to get pointer to our context
c = *(RDiskStorage_t**)d->dCtlStorage;
// Handle status request based on csCode
switch (p->csCode) {
case kDriveStatus:
BlockMove(*d->dCtlStorage, &p->csParam, sizeof(DrvSts2));
return noErr;
default: return statusErr;
}
}
#pragma parameter __D0 RDiskClose(__A0, __A1)
OSErr RDiskClose(IOParamPtr p, DCtlPtr d) {
// If dCtlStorage not null, dispose of it
if (!d->dCtlStorage) { return noErr; }
RDiskStorage_t *c = *(RDiskStorage_t**)d->dCtlStorage;
HUnlock(d->dCtlStorage);
DisposeHandle(d->dCtlStorage);
d->dCtlStorage = NULL;
return noErr;
}

195
rdisk.h Normal file
View File

@ -0,0 +1,195 @@
#ifndef RDISK_H
#define RDISK_H
//#define RDiskSize (0x00180000L)
#define RDiskBuf ((char*)0x40880000)
#define BufPtr ((Ptr*)0x10C)
#define MemTop ((Ptr*)0x108)
#define MMU32bit ((char*)0xCB2)
#pragma parameter __D0 RDiskReadXPRAM(__D0, __D1, __A0)
OSErr RDiskReadXPRAM(short numBytes, short whichByte, Ptr dest) = {0x4840, 0x3001, 0xA051};
#pragma parameter __D0 RDiskAddDrive(__D1, __D0, __A0)
OSErr RDiskAddDrive(short drvrRefNum, short drvNum, DrvQElPtr dq) = {0x4840, 0x3001, 0xA04E};
static inline char RDiskIsRPressed() { return *((char*)0x175) & 0x80; }
static inline char RDiskIsAPressed() { return *((char*)0x174) & 0x01; }
typedef void (*RDiskCopy_t)(Ptr, Ptr, unsigned long);
#define copy24(s, d, b) { RDiskCopy_t copy24 = (RDiskCopy_t)RDiskCopy24; copy24(s, d, b); }
//#define RDISK_COMPRESS_ICON_ENABLE
#define RDISK_ICON_SIZE (285)
typedef struct RDiskStorage_s {
DrvSts2 status;
char initialized;
Ptr ramdisk;
#ifdef RDISK_COMPRESS_ICON_ENABLE
char icon[RDISK_ICON_SIZE];
#endif
} RDiskStorage_t;
#define PackBits_Repeat(count) (-1 * (count - 1))
#define PackBits_Literal(count) (count - 1)
#define RDISK_COMPRESSED_ICON_SIZE (87)
#ifdef RDISK_COMPRESS_ICON_ENABLE
#include <Quickdraw.h>
const char const RDiskIconCompressed[RDISK_COMPRESSED_ICON_SIZE] = {
PackBits_Repeat(76), 0b00000000, /*
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000, */
PackBits_Repeat(4), 0b11111111, /*
0b11111111, 0b11111111, 0b11111111, 0b11111111, */
PackBits_Literal(36),
0b10000000, 0b00000000, 0b00000000, 0b00000001,
0b10001111, 0b00011110, 0b00111100, 0b01111001,
0b10001001, 0b00010010, 0b00100100, 0b01001001,
0b10001001, 0b00010010, 0b00100100, 0b01001001,
0b10001001, 0b00010010, 0b00100100, 0b01001001,
0b10001111, 0b00011110, 0b00111100, 0b01111001,
0b11000000, 0b00000000, 0b00000000, 0b00000001,
0b01010101, 0b01010101, 0b11010101, 0b01010101,
0b01111111, 0b11111111, 0b01111111, 0b11111111,
PackBits_Repeat(12), 0b00000000, /*
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000, */
PackBits_Repeat(76), 0b00000000, /*
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000, */
PackBits_Repeat(32), 0b11111111, /*
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111, */
PackBits_Literal(1), 0b01111111,
PackBits_Repeat(3), 0b11111111, /*
0b01111111, 0b11111111, 0b11111111, 0b11111111, */
PackBits_Literal(1), 0b01111111,
PackBits_Repeat(3), 0b11111111, /*
0b01111111, 0b11111111, 0b11111111, 0b11111111, */
PackBits_Repeat(12), 0b00000000, /*
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000, */
PackBits_Literal(29),
27, 'G', 'a', 'r', 'r', 'e', 't', 't', '\'', 's', ' ',
'W', 'o', 'r', 'k', 's', 'h', 'o', 'p', ' ',
'R', 'O', 'M', ' ', 'D', 'i', 's', 'k', 0
};
#else
const char const RDiskIcon[RDISK_ICON_SIZE] = {
// Icon
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b10000000, 0b00000000, 0b00000000, 0b00000001,
0b10001111, 0b00011110, 0b00111100, 0b01111001,
0b10001001, 0b00010010, 0b00100100, 0b01001001,
0b10001001, 0b00010010, 0b00100100, 0b01001001,
0b10001001, 0b00010010, 0b00100100, 0b01001001,
0b10001111, 0b00011110, 0b00111100, 0b01111001,
0b11000000, 0b00000000, 0b00000000, 0b00000001,
0b01010101, 0b01010101, 0b11010101, 0b01010101,
0b01111111, 0b11111111, 0b01111111, 0b11111111,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
// Mask
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b01111111, 0b11111111, 0b11111111, 0b11111111,
0b01111111, 0b11111111, 0b11111111, 0b11111111,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
27, 'G', 'a', 'r', 'r', 'e', 't', 't', '\'', 's', ' ',
'W', 'o', 'r', 'k', 's', 'h', 'o', 'p', ' ',
'R', 'O', 'M', ' ', 'D', 'i', 's', 'k', 0
};
#endif
#endif