- improved compatibility of multiple depth/resolution handling with versions

of MacOS before 7.6:
   - Apple mode IDs are now allocated contiguously from 0x80 (the video_*.cpp
     module must call video_init_depth_list() after adding all modes)
   - if the video driver didn't receive a GetVideoParameters call, it patches
     ScrnBase and the main GDevice upon a video mode switch (otherwise MacOS
     will continue to use the old frame buffer base)
   - the rowBytes values in the video parameters slot resources are correct
     for all bit depths
This commit is contained in:
cebix 2001-07-03 19:20:47 +00:00
parent cf22cb032a
commit d0a4b3e5fc
6 changed files with 115 additions and 52 deletions

View File

@ -129,6 +129,7 @@ static void set_video_monitor(uint32 width, uint32 height, uint32 bytes_per_row,
}
VideoModes.push_back(mode);
video_init_depth_list();
VideoMonitor.mode = mode;
}

View File

@ -206,6 +206,7 @@ static void set_video_monitor(uint32 width, uint32 height, uint32 bytes_per_row,
}
VideoModes.push_back(mode);
video_init_depth_list();
VideoMonitor.mode = mode;
}

View File

@ -1410,6 +1410,7 @@ bool VideoInit(bool classic)
}
} else
add_mode(default_width, default_height, 0x80, TrivialBytesPerRow(default_width, default_depth), default_depth);
video_init_depth_list();
// Find requested default mode and open display
if (VideoModes.size() == 1)

View File

@ -55,14 +55,17 @@ enum video_depth {
VDEPTH_32BIT // "Millions"
};
// For compatibility reasons with older (pre-Display Manager) versions of
// MacOS, the Apple modes must start at 0x80 and be contiguous. Therefore
// we construct an array to map the depth codes to the corresponding Apple
// mode. This array is initialized by video_init_depth_list() which must
// be called by the platform-dependant VideoInit() routine after filling
// the VideoModes array.
extern uint16 apple_mode_for_depth[6];
inline uint16 DepthToAppleMode(video_depth depth)
{
return depth + 0x80;
}
inline video_depth AppleModeToDepth(uint16 mode)
{
return video_depth(mode - 0x80);
return apple_mode_for_depth[depth];
}
inline bool IsDirectMode(video_depth depth)
@ -70,11 +73,6 @@ inline bool IsDirectMode(video_depth depth)
return depth == VDEPTH_16BIT || depth == VDEPTH_32BIT;
}
inline bool IsDirectMode(uint16 mode)
{
return IsDirectMode(AppleModeToDepth(mode));
}
// Return the depth code that corresponds to the specified bits-per-pixel value
inline video_depth DepthModeForPixelDepth(int depth)
{
@ -177,4 +175,13 @@ extern void video_switch_to_mode(const video_mode &mode);
// or gamma table (in direct modes)
extern void video_set_palette(uint8 *pal, int num);
// Check whether a mode with the specified depth exists
extern bool video_has_depth(video_depth depth);
// Get bytes-per-row value for specified resolution/depth
extern uint32 video_bytes_per_row(video_depth depth, uint32 id);
// Initialize apple_mode_for_depth[] array from VideoModes list
extern void video_init_depth_list(void);
#endif

View File

@ -46,19 +46,6 @@ static uint32 p;
static int slot_rom_size = 0;
// Check whether a mode with the specified depth exists
static bool has_depth(video_depth depth)
{
vector<video_mode>::const_iterator i = VideoModes.begin(), end = VideoModes.end();
while (i != end) {
if (i->depth == depth)
return true;
++i;
}
return false;
}
/*
* Construct slot declaration ROM and copy it into the Mac ROM (must be called after VideoInit())
*/
@ -118,16 +105,16 @@ static void PString(char *str)
srom[p++] = 0;
}
static uint32 VModeParms(uint32 width, uint32 height, uint32 bytes_per_row, video_depth depth)
static uint32 VModeParms(const video_mode &mode, video_depth depth)
{
uint32 ret = p;
Long(50); // Length
Long(0); // Base offset
Word(bytes_per_row); // Row bytes
Word(video_bytes_per_row(depth, mode.resolution_id));
Word(0); // Bounds
Word(0);
Word(height);
Word(width);
Word(mode.y);
Word(mode.x);
Word(0); // Version
Word(0); // Pack type
Long(0); // Pack size
@ -315,12 +302,12 @@ bool InstallSlotROM(void)
Offs(0x80, defaultGamma);
EndOfList();
vidModeParms1 = VModeParms(VideoMonitor.mode.x, VideoMonitor.mode.y, VideoMonitor.mode.bytes_per_row, VDEPTH_1BIT);
vidModeParms2 = VModeParms(VideoMonitor.mode.x, VideoMonitor.mode.y, VideoMonitor.mode.bytes_per_row, VDEPTH_2BIT);
vidModeParms4 = VModeParms(VideoMonitor.mode.x, VideoMonitor.mode.y, VideoMonitor.mode.bytes_per_row, VDEPTH_4BIT);
vidModeParms8 = VModeParms(VideoMonitor.mode.x, VideoMonitor.mode.y, VideoMonitor.mode.bytes_per_row, VDEPTH_8BIT);
vidModeParms16 = VModeParms(VideoMonitor.mode.x, VideoMonitor.mode.y, VideoMonitor.mode.bytes_per_row, VDEPTH_16BIT);
vidModeParms32 = VModeParms(VideoMonitor.mode.x, VideoMonitor.mode.y, VideoMonitor.mode.bytes_per_row, VDEPTH_32BIT);
vidModeParms1 = VModeParms(VideoMonitor.mode, VDEPTH_1BIT);
vidModeParms2 = VModeParms(VideoMonitor.mode, VDEPTH_2BIT);
vidModeParms4 = VModeParms(VideoMonitor.mode, VDEPTH_4BIT);
vidModeParms8 = VModeParms(VideoMonitor.mode, VDEPTH_8BIT);
vidModeParms16 = VModeParms(VideoMonitor.mode, VDEPTH_16BIT);
vidModeParms32 = VModeParms(VideoMonitor.mode, VDEPTH_32BIT);
vidMode1 = VModeDesc(vidModeParms1, false);
vidMode2 = VModeDesc(vidModeParms2, false);
@ -338,18 +325,18 @@ bool InstallSlotROM(void)
Offs(0x0b, minorLength); // Frame buffer length
Offs(0x40, gammaDir); // Gamma directory
Rsrc(0x7d, 6); // Video attributes: Default to color, built-in
if (has_depth(VDEPTH_1BIT))
Offs(0x80, vidMode1); // Video mode parameters for 1 bit
if (has_depth(VDEPTH_2BIT))
Offs(0x81, vidMode2); // Video mode parameters for 2 bit
if (has_depth(VDEPTH_4BIT))
Offs(0x82, vidMode4); // Video mode parameters for 4 bit
if (has_depth(VDEPTH_8BIT))
Offs(0x83, vidMode8); // Video mode parameters for 8 bit
if (has_depth(VDEPTH_16BIT))
Offs(0x84, vidMode16); // Video mode parameters for 16 bit
if (has_depth(VDEPTH_32BIT))
Offs(0x85, vidMode32); // Video mode parameters for 32 bit
if (video_has_depth(VDEPTH_1BIT))
Offs(DepthToAppleMode(VDEPTH_1BIT), vidMode1); // Video mode parameters for 1 bit
if (video_has_depth(VDEPTH_2BIT))
Offs(DepthToAppleMode(VDEPTH_2BIT), vidMode2); // Video mode parameters for 2 bit
if (video_has_depth(VDEPTH_4BIT))
Offs(DepthToAppleMode(VDEPTH_4BIT), vidMode4); // Video mode parameters for 4 bit
if (video_has_depth(VDEPTH_8BIT))
Offs(DepthToAppleMode(VDEPTH_8BIT), vidMode8); // Video mode parameters for 8 bit
if (video_has_depth(VDEPTH_16BIT))
Offs(DepthToAppleMode(VDEPTH_16BIT), vidMode16); // Video mode parameters for 16 bit
if (video_has_depth(VDEPTH_32BIT))
Offs(DepthToAppleMode(VDEPTH_32BIT), vidMode32); // Video mode parameters for 32 bit
EndOfList();
// CPU sResource

View File

@ -45,12 +45,16 @@ vector<video_mode> VideoModes;
// Description of the main monitor
monitor_desc VideoMonitor;
// Depth code -> Apple mode mapping
uint16 apple_mode_for_depth[6];
// Local variables (per monitor)
struct {
monitor_desc *desc; // Pointer to description of monitor handled by this instance of the driver
uint8 palette[256 * 3]; // Color palette, 256 entries, RGB
bool luminance_mapping; // Luminance mapping on/off
bool interrupts_enabled; // VBL interrupts on/off
bool dm_present; // We received a GetVideoParameters call, so the Display Manager seems to be present
uint32 gamma_table; // Mac address of gamma table
int alloc_gamma_table_size; // Allocated size of gamma table
uint16 current_mode; // Currently selected depth/resolution
@ -61,6 +65,38 @@ struct {
} VidLocal;
/*
* Initialize apple_mode_for_depth[] array from VideoModes list
*/
void video_init_depth_list(void)
{
uint16 mode = 0x80;
for (int depth = VDEPTH_1BIT; depth <= VDEPTH_32BIT; depth++) {
if (video_has_depth(video_depth(depth)))
apple_mode_for_depth[depth] = mode++;
else
apple_mode_for_depth[depth] = 0;
}
}
/*
* Check whether a mode with the specified depth exists
*/
bool video_has_depth(video_depth depth)
{
vector<video_mode>::const_iterator i = VideoModes.begin(), end = VideoModes.end();
while (i != end) {
if (i->depth == depth)
return true;
++i;
}
return false;
}
/*
* Check whether specified resolution ID is one of the supported resolutions
*/
@ -121,6 +157,24 @@ static void get_size_of_resolution(uint32 id, uint32 &x, uint32 &y)
return;
}
}
x = y = 0;
}
/*
* Get bytes-per-row value for specified resolution/depth
*/
uint32 video_bytes_per_row(video_depth depth, uint32 id)
{
vector<video_mode>::const_iterator i, end = VideoModes.end();
for (i = VideoModes.begin(); i != end; ++i) {
if (i->depth == depth && i->resolution_id == id)
return i->bytes_per_row;
}
uint32 x, y;
get_size_of_resolution(id, x, y);
return TrivialBytesPerRow(x, depth);
}
@ -279,7 +333,7 @@ static bool set_gamma_table(uint32 user_table)
Mac2Mac_memcpy(table, user_table, size);
}
if (IsDirectMode(VidLocal.current_mode))
if (IsDirectMode(VidLocal.desc->mode))
load_ramp_palette();
return true;
@ -351,6 +405,16 @@ static void switch_mode(const video_mode &mode, uint32 param, uint32 dce)
// Update frame buffer base in DCE and param block
WriteMacInt32(dce + dCtlDevBase, frame_base);
WriteMacInt32(param + csBaseAddr, frame_base);
// Patch frame buffer base address for MacOS versions <7.6
if (!VidLocal.dm_present) { // Only do this when no Display Manager seems to be present; otherwise, the screen will not get redrawn
WriteMacInt32(0x824, frame_base); // ScrnBase
uint32 gdev = ReadMacInt32(0x8a4); // MainDevice
gdev = ReadMacInt32(gdev);
uint32 pmap = ReadMacInt32(gdev + 0x16); // gdPMap
pmap = ReadMacInt32(pmap);
WriteMacInt32(pmap, frame_base); // baseAddr
}
}
@ -374,6 +438,7 @@ int16 VideoDriverOpen(uint32 pb, uint32 dce)
VidLocal.current_id = VidLocal.desc->mode.resolution_id;
VidLocal.preferred_mode = VidLocal.current_mode;
VidLocal.preferred_id = VidLocal.current_id;
VidLocal.dm_present = false;
// Allocate Slot Manager parameter block in Mac RAM
M68kRegisters r;
@ -429,7 +494,7 @@ int16 VideoDriverControl(uint32 pb, uint32 dce)
case cscSetEntries: // Set palette
case cscDirectSetEntries: {
D(bug(" (Direct)SetEntries table %08x, count %d, start %d\n", ReadMacInt32(param + csTable), ReadMacInt16(param + csCount), ReadMacInt16(param + csStart)));
bool is_direct = IsDirectMode(VidLocal.current_mode);
bool is_direct = IsDirectMode(VidLocal.desc->mode);
if (code == cscSetEntries && is_direct)
return controlErr;
if (code == cscDirectSetEntries && !is_direct)
@ -524,20 +589,20 @@ int16 VideoDriverControl(uint32 pb, uint32 dce)
0xffff0000, // 16 bpp
0xffffffff // 32 bpp
};
uint32 p = VidLocal.desc->mac_frame_base;
uint32 frame_base = VidLocal.desc->mac_frame_base;
uint32 pat = pattern[VidLocal.desc->mode.depth];
bool invert = (VidLocal.desc->mode.depth == VDEPTH_32BIT);
for (uint32 y=0; y<VidLocal.desc->mode.y; y++) {
for (uint32 x=0; x<VidLocal.desc->mode.bytes_per_row; x+=4) {
WriteMacInt32(p + x, pat);
WriteMacInt32(frame_base + x, pat);
if (invert)
pat = ~pat;
}
p += VidLocal.desc->mode.bytes_per_row;
frame_base += VidLocal.desc->mode.bytes_per_row;
pat = ~pat;
}
if (IsDirectMode(VidLocal.current_mode))
if (IsDirectMode(VidLocal.desc->mode))
load_ramp_palette();
return noErr;
@ -774,6 +839,7 @@ int16 VideoDriverStatus(uint32 pb, uint32 dce)
uint32 id = ReadMacInt32(param + csDisplayModeID);
uint16 mode = ReadMacInt16(param + csDepthMode);
D(bug(" GetVideoParameters %04x/%08x\n", mode, id));
VidLocal.dm_present = true; // Display Manager seems to be present
vector<video_mode>::const_iterator i, end = VideoModes.end();
for (i = VideoModes.begin(); i != end; ++i) {