macemu/BasiliskII/src/slot_rom.cpp

479 lines
13 KiB
C++

/*
* slot_rom.cpp - Slot declaration ROM
*
* Basilisk II (C) Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* SEE ALSO
* Inside Macintosh: Devices, chapter 2 "Slot Manager"
* Designing Cards and Drivers for the Macintosh Family, Second Edition
*/
#include <stdio.h>
#include <string.h>
#include "sysdeps.h"
#include "cpu_emulation.h"
#include "main.h"
#include "video.h"
#include "emul_op.h"
#include "version.h"
#include "slot_rom.h"
// Temporary buffer for slot ROM
static uint8 srom[4096];
// Index in srom
static uint32 p;
// Length of slot ROM
static int slot_rom_size = 0;
/*
* Construct slot declaration ROM and copy it into the Mac ROM (must be called after VideoInit())
*/
static void Offs(uint8 type, uint32 ptr)
{
uint32 offs = ptr - p;
srom[p++] = type;
srom[p++] = offs >> 16;
srom[p++] = offs >> 8;
srom[p++] = offs;
}
static void Rsrc(uint8 type, uint32 data)
{
srom[p++] = type;
srom[p++] = data >> 16;
srom[p++] = data >> 8;
srom[p++] = data;
}
static void EndOfList(void)
{
srom[p++] = 0xff;
srom[p++] = 0;
srom[p++] = 0;
srom[p++] = 0;
}
static void Long(uint32 data)
{
srom[p++] = data >> 24;
srom[p++] = data >> 16;
srom[p++] = data >> 8;
srom[p++] = data;
}
static void Word(uint16 data)
{
srom[p++] = data >> 8;
srom[p++] = uint8(data);
}
static void String(const char *str)
{
while ((srom[p++] = *str++) != 0) ;
if (p & 1)
srom[p++] = 0;
}
static void PString(const char *str)
{
srom[p++] = uint8(strlen(str));
while ((srom[p++] = *str++) != 0) ;
p--;
if (p & 1)
srom[p++] = 0;
}
static uint32 VModeParms(const monitor_desc &m, video_depth depth)
{
const video_mode &mode = m.get_current_mode();
uint32 ret = p;
Long(50); // Length
Long(0); // Base offset
Word(m.get_bytes_per_row(depth, mode.resolution_id));
Word(0); // Bounds
Word(0);
Word(mode.y);
Word(mode.x);
Word(0); // Version
Word(0); // Pack type
Long(0); // Pack size
Long(0x00480000); // HRes
Long(0x00480000); // VRes
switch (depth) {
case VDEPTH_1BIT:
Word(0); // Pixel type (indirect)
Word(1); // Pixel size
Word(1); // CmpCount
Word(1); // CmpSize
break;
case VDEPTH_2BIT:
Word(0); // Pixel type (indirect)
Word(2); // Pixel size
Word(1); // CmpCount
Word(2); // CmpSize
break;
case VDEPTH_4BIT:
Word(0); // Pixel type (indirect)
Word(4); // Pixel size
Word(1); // CmpCount
Word(4); // CmpSize
break;
case VDEPTH_8BIT:
Word(0); // Pixel type (indirect)
Word(8); // Pixel size
Word(1); // CmpCount
Word(8); // CmpSize
break;
case VDEPTH_16BIT:
Word(16); // Pixel type (direct)
Word(16); // Pixel size
Word(3); // CmpCount
Word(5); // CmpSize
break;
case VDEPTH_32BIT:
Word(16); // Pixel type (direct)
Word(32); // Pixel size
Word(3); // CmpCount
Word(8); // CmpSize
break;
}
Long(0); // Plane size
Long(0); // Reserved
return ret;
}
static uint32 VModeDesc(uint32 params, bool direct)
{
uint32 ret = p;
Offs(0x01, params); // Video parameters
Rsrc(0x03, 1); // Page count
Rsrc(0x04, direct ? 2 : 0); // Device type
EndOfList();
return ret;
}
static uint32 VMonitor(const monitor_desc &m, uint32 videoType, uint32 videoName, uint32 vidDrvrDir, uint32 gammaDir)
{
uint32 minorBase, minorLength;
uint32 vidModeParms1, vidModeParms2, vidModeParms4, vidModeParms8, vidModeParms16, vidModeParms32;
uint32 vidMode1, vidMode2, vidMode4, vidMode8, vidMode16, vidMode32;
uint32 ret;
minorBase = p;
Long(m.get_mac_frame_base()); // Frame buffer base
minorLength = p;
Long(0); // Frame buffer size (unspecified)
vidModeParms1 = VModeParms(m, VDEPTH_1BIT);
vidModeParms2 = VModeParms(m, VDEPTH_2BIT);
vidModeParms4 = VModeParms(m, VDEPTH_4BIT);
vidModeParms8 = VModeParms(m, VDEPTH_8BIT);
vidModeParms16 = VModeParms(m, VDEPTH_16BIT);
vidModeParms32 = VModeParms(m, VDEPTH_32BIT);
vidMode1 = VModeDesc(vidModeParms1, false);
vidMode2 = VModeDesc(vidModeParms2, false);
vidMode4 = VModeDesc(vidModeParms4, false);
vidMode8 = VModeDesc(vidModeParms8, false);
vidMode16 = VModeDesc(vidModeParms16, true);
vidMode32 = VModeDesc(vidModeParms32, true);
ret = p;
Offs(0x01, videoType); // Video type descriptor
Offs(0x02, videoName); // Driver name
Offs(0x04, vidDrvrDir); // Driver directory
Rsrc(0x08, 0x4232); // Hardware device ID ('B2')
Offs(0x0a, minorBase); // Frame buffer base
Offs(0x0b, minorLength); // Frame buffer length
Offs(0x40, gammaDir); // Gamma directory
Rsrc(0x7d, 6); // Video attributes: Default to color, built-in
if (m.has_depth(VDEPTH_1BIT))
Offs(uint8(m.depth_to_apple_mode(VDEPTH_1BIT)), vidMode1); // Video mode parameters for 1 bit
if (m.has_depth(VDEPTH_2BIT))
Offs(uint8(m.depth_to_apple_mode(VDEPTH_2BIT)), vidMode2); // Video mode parameters for 2 bit
if (m.has_depth(VDEPTH_4BIT))
Offs(uint8(m.depth_to_apple_mode(VDEPTH_4BIT)), vidMode4); // Video mode parameters for 4 bit
if (m.has_depth(VDEPTH_8BIT))
Offs(uint8(m.depth_to_apple_mode(VDEPTH_8BIT)), vidMode8); // Video mode parameters for 8 bit
if (m.has_depth(VDEPTH_16BIT))
Offs(uint8(m.depth_to_apple_mode(VDEPTH_16BIT)), vidMode16); // Video mode parameters for 16 bit
if (m.has_depth(VDEPTH_32BIT))
Offs(uint8(m.depth_to_apple_mode(VDEPTH_32BIT)), vidMode32); // Video mode parameters for 32 bit
EndOfList();
return ret;
}
bool InstallSlotROM(void)
{
uint32 boardType, boardName, vendorID, revLevel, partNum, date;
uint32 vendorInfo, sRsrcBoard;
uint32 videoType, videoName, videoDrvr, vidDrvrDir;
uint32 defaultGamma, gammaDir;
uint32 cpuType, cpuName, cpuMajor, cpuMinor, sRsrcCPU;
uint32 etherType, etherName, etherDrvr, etherDrvrDir, sRsrcEther;
uint32 sRsrcDir;
vector<monitor_desc *>::const_iterator m, mend = VideoMonitors.end();
vector<uint32> sRsrcVideo;
char str[256];
int i;
p = 0;
// Board sResource
boardType = p; // Literals
Word(1); Word(0); Word(0); Word(0); // Board sResource
boardName = p;
String("Basilisk II Slot ROM");
vendorID = p;
String("Christian Bauer");
revLevel = p;
sprintf(str, "V%d.%d", VERSION_MAJOR, VERSION_MINOR);
String(str);
partNum = p;
String("BasiliskII");
date = p;
String(__DATE__);
vendorInfo = p; // Vendor Info
Offs(0x01, vendorID); // Vendor ID
Offs(0x03, revLevel); // Revision level
Offs(0x04, partNum); // Part number
Offs(0x05, date); // ROM build date
EndOfList();
sRsrcBoard = p;
Offs(0x01, boardType); // Board descriptor
Offs(0x02, boardName); // Board name
Rsrc(0x20, 0x4232); // Board ID ('B2')
Offs(0x24, vendorInfo); // Vendor Info
EndOfList();
videoType = p;
Word(3); Word(1); Word(1); Word(0x4232); // Display Video Apple 'B2'
videoName = p;
String("Display_Video_Apple_Basilisk");
videoDrvr = p; // Video driver
Long(0x72); // Length
Word(0x4c00); Word(0); Word(0); Word(0);
Word(0x32); // Open offset
Word(0x36); // Prime offset
Word(0x3a); // Control offset
Word(0x46); // Status offset
Word(0x6c); // Close offset
PString(".Display_Video_Apple_Basilisk");
Word(1); // Driver version
Word(M68K_EMUL_OP_VIDEO_OPEN); // Open()
Word(0x4e75);
Word(0x70ff); // Prime()
Word(0x600e);
Word(M68K_EMUL_OP_VIDEO_CONTROL); // Control()
Word(0x0c68); Word(0x0001); Word(0x001a);
Word(0x6604);
Word(0x4e75);
Word(M68K_EMUL_OP_VIDEO_STATUS); // Status()
Word(0x3228); Word(0x0006); // IOReturn
Word(0x0801); Word(0x0009);
Word(0x670c);
Word(0x4a40);
Word(0x6f02);
Word(0x4240);
Word(0x3140); Word(0x0010);
Word(0x4e75);
Word(0x4a40);
Word(0x6f04);
Word(0x4240);
Word(0x4e75);
Word(0x2f38); Word(0x08fc);
Word(0x4e75);
Word(0x70e8); // Close()
Word(0x4e75);
vidDrvrDir = p; // Driver directory
Offs(0x02, videoDrvr); // sMacOS68020
EndOfList();
defaultGamma = p; // Gamma table
Long(38 + 0x100); // Length
Word(0x2000); // Resource ID
String("Mac HiRes Std Gamma");
Word(0); // Version
Word(0); // Type
Word(0); // FormulaSize
Word(1); // ChanCnt
Word(0x0100); // DataCnt
Word(8); // ChanWidth
Long(0x0005090B); Long(0x0E101315); Long(0x17191B1D); Long(0x1E202224);
Long(0x2527282A); Long(0x2C2D2F30); Long(0x31333436); Long(0x37383A3B);
Long(0x3C3E3F40); Long(0x42434445); Long(0x4748494A); Long(0x4B4D4E4F);
Long(0x50515254); Long(0x55565758); Long(0x595A5B5C); Long(0x5E5F6061);
Long(0x62636465); Long(0x66676869); Long(0x6A6B6C6D); Long(0x6E6F7071);
Long(0x72737475); Long(0x76777879); Long(0x7A7B7C7D); Long(0x7E7F8081);
Long(0x81828384); Long(0x85868788); Long(0x898A8B8C); Long(0x8C8D8E8F);
Long(0x90919293); Long(0x94959596); Long(0x9798999A); Long(0x9B9B9C9D);
Long(0x9E9FA0A1); Long(0xA1A2A3A4); Long(0xA5A6A6A7); Long(0xA8A9AAAB);
Long(0xABACADAE); Long(0xAFB0B0B1); Long(0xB2B3B4B4); Long(0xB5B6B7B8);
Long(0xB8B9BABB); Long(0xBCBCBDBE); Long(0xBFC0C0C1); Long(0xC2C3C3C4);
Long(0xC5C6C7C7); Long(0xC8C9CACA); Long(0xCBCCCDCD); Long(0xCECFD0D0);
Long(0xD1D2D3D3); Long(0xD4D5D6D6); Long(0xD7D8D9D9); Long(0xDADBDCDC);
Long(0xDDDEDFDF); Long(0xE0E1E1E2); Long(0xE3E4E4E5); Long(0xE6E7E7E8);
Long(0xE9E9EAEB); Long(0xECECEDEE); Long(0xEEEFF0F1); Long(0xF1F2F3F3);
Long(0xF4F5F5F6); Long(0xF7F8F8F9); Long(0xFAFAFBFC); Long(0xFCFDFEFF);
gammaDir = p; // Gamma directory
Offs(0x80, defaultGamma);
EndOfList();
for (m = VideoMonitors.begin(); m != mend; ++m)
sRsrcVideo.push_back(VMonitor(**m, videoType, videoName, vidDrvrDir, gammaDir));
// CPU sResource
cpuType = p; // Literals
Word(10); Word(3); Word(0); Word(24); // CPU 68020
cpuName = p;
String("CPU_68020");
cpuMajor = p;
Long(0); Long(0x7fffffff);
cpuMinor = p;
Long(0xf0800000); Long(0xf0ffffff);
sRsrcCPU = p;
Offs(0x01, cpuType); // Type descriptor
Offs(0x02, cpuName); // CPU name
Offs(0x81, cpuMajor); // Major RAM space
Offs(0x82, cpuMinor); // Minor RAM space
EndOfList();
// Ethernet sResource
etherType = p; // Literals
Word(4); Word(1); Word(1); Word(0x4232); // Network Ethernet Apple 'B2'
etherName = p;
String("Network_Ethernet_Apple_BasiliskII");
etherDrvr = p; // Video driver
Long(0x88); // Length
Word(0x4400); Word(0); Word(0); Word(0);
Word(0x4a); // Open offset
Word(0x4e); // Prime offset
Word(0x52); // Control offset
Word(0x4e); // Status offset
Word(0x82); // Close offset
PString(".ENET");
Word(0x0111); Word(0x8000); // Driver version
Word(0);
PString("1.1.1 ");
PString("Basilisk II Ethernet Network Driver");
Word(M68K_EMUL_OP_ETHER_OPEN); // Open()
Word(0x4e75);
Word(0x70ef); // Prime()/Status()
Word(0x600c);
Word(M68K_EMUL_OP_ETHER_CONTROL); // Control()
Word(0x0c68); Word(0x0001); Word(0x001a);
Word(0x6602);
Word(0x4e75);
Word(0x3228); Word(0x0006); // IOReturn
Word(0x0801); Word(0x0009);
Word(0x670c);
Word(0x4a40);
Word(0x6f02);
Word(0x4240);
Word(0x3140); Word(0x0010);
Word(0x4e75);
Word(0x4a40);
Word(0x6f04);
Word(0x4240);
Word(0x4e75);
Word(0x2f38); Word(0x08fc);
Word(0x4e75);
Word(0x70e8); // Close()
Word(0x4e75);
etherDrvrDir = p; // Driver directory
Offs(0x02, etherDrvr); // sMacOS68020
EndOfList();
sRsrcEther = p;
Offs(0x01, etherType); // Type descriptor
Offs(0x02, etherName); // Driver name
Offs(0x04, etherDrvrDir); // Driver directory
Rsrc(0x07, 2); // Flags: OpenAtStart
Rsrc(0x08, 0x4232); // Hardware device ID ('B2')
EndOfList();
// sResource directory
sRsrcDir = p;
Offs(0x01, sRsrcBoard);
for (m = VideoMonitors.begin(), i = 0; m != mend; ++m, ++i)
Offs((*m)->get_slot_id(), sRsrcVideo[i]);
Offs(0xf0, sRsrcCPU);
Offs(0xf1, sRsrcEther);
EndOfList();
// Format/header block
Offs(0, sRsrcDir); // sResource directory
Long(p + 16); // Length of declaration data
Long(0); // CRC (calculated later)
Word(0x0101); // Rev. level, format
Long(0x5a932bc7); // Test pattern
Word(0x000f); // Byte lanes
// Copy slot ROM to Mac ROM
slot_rom_size = p;
memcpy(ROMBaseHost + ROMSize - slot_rom_size, srom, slot_rom_size);
// Calculate checksum
ChecksumSlotROM();
return true;
}
/*
* Calculate slot ROM checksum (in-place)
*/
void ChecksumSlotROM(void)
{
// Calculate CRC
uint8 *p = ROMBaseHost + ROMSize - slot_rom_size;
p[slot_rom_size - 12] = 0;
p[slot_rom_size - 11] = 0;
p[slot_rom_size - 10] = 0;
p[slot_rom_size - 9] = 0;
uint32 crc = 0;
for (int i=0; i<slot_rom_size; i++) {
crc = (crc << 1) | (crc >> 31);
crc += p[i];
}
p[slot_rom_size - 12] = crc >> 24;
p[slot_rom_size - 11] = crc >> 16;
p[slot_rom_size - 10] = crc >> 8;
p[slot_rom_size - 9] = crc;
}