mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-09-28 15:54:44 +00:00
- 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:
parent
cf22cb032a
commit
d0a4b3e5fc
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user