From d0a4b3e5fcac4769e7be4d07982ace3cd132d5ad Mon Sep 17 00:00:00 2001 From: cebix <> Date: Tue, 3 Jul 2001 19:20:47 +0000 Subject: [PATCH] - 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 --- BasiliskII/src/AmigaOS/video_amiga.cpp | 1 + BasiliskII/src/BeOS/video_beos.cpp | 1 + BasiliskII/src/Unix/video_x.cpp | 1 + BasiliskII/src/include/video.h | 29 ++++++---- BasiliskII/src/slot_rom.cpp | 57 ++++++++----------- BasiliskII/src/video.cpp | 78 ++++++++++++++++++++++++-- 6 files changed, 115 insertions(+), 52 deletions(-) diff --git a/BasiliskII/src/AmigaOS/video_amiga.cpp b/BasiliskII/src/AmigaOS/video_amiga.cpp index eaa9a24a..d6149ad3 100644 --- a/BasiliskII/src/AmigaOS/video_amiga.cpp +++ b/BasiliskII/src/AmigaOS/video_amiga.cpp @@ -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; } diff --git a/BasiliskII/src/BeOS/video_beos.cpp b/BasiliskII/src/BeOS/video_beos.cpp index a44365f3..10708ca4 100644 --- a/BasiliskII/src/BeOS/video_beos.cpp +++ b/BasiliskII/src/BeOS/video_beos.cpp @@ -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; } diff --git a/BasiliskII/src/Unix/video_x.cpp b/BasiliskII/src/Unix/video_x.cpp index 43f0af41..9e8689d6 100644 --- a/BasiliskII/src/Unix/video_x.cpp +++ b/BasiliskII/src/Unix/video_x.cpp @@ -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) diff --git a/BasiliskII/src/include/video.h b/BasiliskII/src/include/video.h index 93cb5332..76314bd6 100644 --- a/BasiliskII/src/include/video.h +++ b/BasiliskII/src/include/video.h @@ -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 diff --git a/BasiliskII/src/slot_rom.cpp b/BasiliskII/src/slot_rom.cpp index 0a2129f1..da4d6222 100644 --- a/BasiliskII/src/slot_rom.cpp +++ b/BasiliskII/src/slot_rom.cpp @@ -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::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 diff --git a/BasiliskII/src/video.cpp b/BasiliskII/src/video.cpp index 999a8e9f..28c43786 100644 --- a/BasiliskII/src/video.cpp +++ b/BasiliskII/src/video.cpp @@ -45,12 +45,16 @@ vector 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::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::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; ymode.y; y++) { for (uint32 x=0; xmode.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::const_iterator i, end = VideoModes.end(); for (i = VideoModes.begin(); i != end; ++i) {