1 |
|
/* |
2 |
|
* video.h - Video/graphics emulation |
3 |
|
* |
4 |
< |
* Basilisk II (C) 1997-2001 Christian Bauer |
4 |
> |
* Basilisk II (C) 1997-2008 Christian Bauer |
5 |
|
* |
6 |
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
* it under the terms of the GNU General Public License as published by |
23 |
|
|
24 |
|
#include <vector> |
25 |
|
|
26 |
+ |
#ifndef NO_STD_NAMESPACE |
27 |
+ |
using std::vector; |
28 |
+ |
#endif |
29 |
+ |
|
30 |
+ |
|
31 |
+ |
/* |
32 |
+ |
Some of the terminology here is completely frelled. In Basilisk II, a |
33 |
+ |
"video mode" refers to a combination of resolution and color depth, and |
34 |
+ |
this information is stored in a video_mode structure. In Apple |
35 |
+ |
documentation, a "mode" historically refers to the color depth only |
36 |
+ |
(because old Macs had fixed-frequency monitors and could not change the |
37 |
+ |
resolution). These "modes" are assigned a number (0x80, 0x81, etc.), |
38 |
+ |
which we here call "Apple mode". When Macs learned how to deal with |
39 |
+ |
multiscan monitors, Apple introduced another type of "mode", also having |
40 |
+ |
numbers starting from 0x80 but refrerring to the resolution and/or video |
41 |
+ |
timing of the display (it's possible to have two modes with the same |
42 |
+ |
dimension but different refresh rates). We call this a "resolution ID". |
43 |
+ |
The combination of "Apple mode" and "ID" corresponds to a Basilisk II |
44 |
+ |
"video mode". To make the confusion worse, the video driver control call |
45 |
+ |
that sets the color depth is called "SetMode" while the one that sets |
46 |
+ |
both depth and resolution is "SwitchMode"... |
47 |
+ |
*/ |
48 |
+ |
|
49 |
|
// Color depth codes |
50 |
|
enum video_depth { |
51 |
|
VDEPTH_1BIT, // 2 colors |
56 |
|
VDEPTH_32BIT // "Millions" |
57 |
|
}; |
58 |
|
|
59 |
+ |
// 1, 2, 4 and 8 bit depths use a color palette |
60 |
|
inline bool IsDirectMode(video_depth depth) |
61 |
|
{ |
62 |
|
return depth == VDEPTH_16BIT || depth == VDEPTH_32BIT; |
63 |
|
} |
64 |
|
|
65 |
< |
inline uint16 DepthToAppleMode(video_depth depth) |
65 |
> |
// Return the depth code that corresponds to the specified bits-per-pixel value |
66 |
> |
inline video_depth DepthModeForPixelDepth(int depth) |
67 |
|
{ |
68 |
< |
return depth + 0x80; |
68 |
> |
switch (depth) { |
69 |
> |
case 1: return VDEPTH_1BIT; |
70 |
> |
case 2: return VDEPTH_2BIT; |
71 |
> |
case 4: return VDEPTH_4BIT; |
72 |
> |
case 8: return VDEPTH_8BIT; |
73 |
> |
case 15: case 16: return VDEPTH_16BIT; |
74 |
> |
case 24: case 32: return VDEPTH_32BIT; |
75 |
> |
default: return VDEPTH_1BIT; |
76 |
> |
} |
77 |
|
} |
78 |
|
|
79 |
< |
inline video_depth AppleModeToDepth(uint16 mode) |
79 |
> |
// Return a bytes-per-row value (assuming no padding) for the specified depth and pixel width |
80 |
> |
inline uint32 TrivialBytesPerRow(uint32 width, video_depth depth) |
81 |
|
{ |
82 |
< |
return video_depth(mode - 0x80); |
82 |
> |
switch (depth) { |
83 |
> |
case VDEPTH_1BIT: return width / 8; |
84 |
> |
case VDEPTH_2BIT: return width / 4; |
85 |
> |
case VDEPTH_4BIT: return width / 2; |
86 |
> |
case VDEPTH_8BIT: return width; |
87 |
> |
case VDEPTH_16BIT: return width * 2; |
88 |
> |
case VDEPTH_32BIT: return width * 4; |
89 |
> |
default: return width; |
90 |
> |
} |
91 |
|
} |
92 |
|
|
93 |
< |
// Description of one video mode |
93 |
> |
|
94 |
> |
/* |
95 |
> |
You are not completely free in your selection of depth/resolution |
96 |
> |
combinations: |
97 |
> |
1) the lowest supported color depth must be available in all |
98 |
> |
resolutions |
99 |
> |
2) if one resolution provides a certain color depth, it must also |
100 |
> |
provide all lower supported depths |
101 |
> |
|
102 |
> |
For example, it is possible to have this set of modes: |
103 |
> |
640x480 @ 8 bit |
104 |
> |
640x480 @ 32 bit |
105 |
> |
800x600 @ 8 bit |
106 |
> |
800x600 @ 32 bit |
107 |
> |
1024x768 @ 8 bit |
108 |
> |
|
109 |
> |
But this is not possible (violates rule 1): |
110 |
> |
640x480 @ 8 bit |
111 |
> |
800x600 @ 8 bit |
112 |
> |
1024x768 @ 1 bit |
113 |
> |
|
114 |
> |
And neither is this (violates rule 2, 640x480 @ 16 bit is missing): |
115 |
> |
640x480 @ 8 bit |
116 |
> |
640x480 @ 32 bit |
117 |
> |
800x600 @ 8 bit |
118 |
> |
800x600 @ 16 bit |
119 |
> |
1024x768 @ 8 bit |
120 |
> |
*/ |
121 |
> |
|
122 |
> |
// Description of a video mode |
123 |
|
struct video_mode { |
124 |
|
uint32 x; // X size of screen (pixels) |
125 |
|
uint32 y; // Y size of screen (pixels) |
126 |
|
uint32 resolution_id; // Resolution ID (should be >= 0x80 and uniquely identify the sets of modes with the same X/Y size) |
56 |
– |
uint32 bytes_per_row; // Bytes per row of frame buffer |
127 |
|
video_depth depth; // Color depth (see definitions above) |
128 |
+ |
uint32 bytes_per_row; // Bytes per row of frame buffer |
129 |
+ |
uint32 user_data; // Free for use by platform-specific code |
130 |
|
}; |
131 |
|
|
132 |
|
inline bool IsDirectMode(const video_mode &mode) |
134 |
|
return IsDirectMode(mode.depth); |
135 |
|
} |
136 |
|
|
65 |
– |
// List of all supported video modes |
66 |
– |
extern vector<video_mode> VideoModes; |
137 |
|
|
138 |
< |
// Description for one (possibly virtual) monitor |
139 |
< |
struct monitor_desc { |
140 |
< |
uint32 mac_frame_base; // Mac frame buffer address |
141 |
< |
video_mode mode; // Currently selected video mode description |
138 |
> |
// Mac video driver per-display private variables (opaque) |
139 |
> |
struct video_locals; |
140 |
> |
|
141 |
> |
|
142 |
> |
// Abstract base class representing one (possibly virtual) monitor |
143 |
> |
// ("monitor" = rectangular display with a contiguous frame buffer) |
144 |
> |
class monitor_desc { |
145 |
> |
public: |
146 |
> |
monitor_desc(const vector<video_mode> &available_modes, video_depth default_depth, uint32 default_id); |
147 |
> |
virtual ~monitor_desc() {} |
148 |
> |
|
149 |
> |
// Get Mac slot ID number |
150 |
> |
uint8 get_slot_id(void) const {return slot_id;} |
151 |
> |
|
152 |
> |
// Get current Mac frame buffer base address |
153 |
> |
uint32 get_mac_frame_base(void) const {return mac_frame_base;} |
154 |
> |
|
155 |
> |
// Set Mac frame buffer base address (called from switch_to_mode()) |
156 |
> |
void set_mac_frame_base(uint32 base) {mac_frame_base = base;} |
157 |
> |
|
158 |
> |
// Get current video mode |
159 |
> |
const video_mode &get_current_mode(void) const {return *current_mode;} |
160 |
> |
|
161 |
> |
// Get Apple mode id for given depth |
162 |
> |
uint16 depth_to_apple_mode(video_depth depth) const {return apple_mode_for_depth[depth];} |
163 |
> |
|
164 |
> |
// Get current color depth |
165 |
> |
uint16 get_apple_mode(void) const {return depth_to_apple_mode(current_mode->depth);} |
166 |
> |
|
167 |
> |
// Get bytes-per-row value for specified resolution/depth |
168 |
> |
// (if the mode isn't supported, make a good guess) |
169 |
> |
uint32 get_bytes_per_row(video_depth depth, uint32 id) const; |
170 |
> |
|
171 |
> |
// Check whether a mode with the specified depth exists on this display |
172 |
> |
bool has_depth(video_depth depth) const; |
173 |
> |
|
174 |
> |
// Mac video driver functions |
175 |
> |
int16 driver_open(void); |
176 |
> |
int16 driver_control(uint16 code, uint32 param, uint32 dce); |
177 |
> |
int16 driver_status(uint16 code, uint32 param); |
178 |
> |
|
179 |
> |
protected: |
180 |
> |
vector<video_mode> modes; // List of supported video modes |
181 |
> |
vector<video_mode>::const_iterator current_mode; // Currently selected video mode |
182 |
> |
|
183 |
> |
uint32 mac_frame_base; // Mac frame buffer address for current mode |
184 |
> |
|
185 |
> |
// Mac video driver per-display private variables/functions |
186 |
> |
private: |
187 |
> |
// Check whether the specified resolution ID is one of the supported resolutions |
188 |
> |
bool has_resolution(uint32 id) const; |
189 |
> |
|
190 |
> |
// Return iterator signifying "invalid mode" |
191 |
> |
vector<video_mode>::const_iterator invalid_mode(void) const {return modes.end();} |
192 |
> |
|
193 |
> |
// Find specified mode (depth/resolution) (or invalid_mode() if not found) |
194 |
> |
vector<video_mode>::const_iterator find_mode(uint16 apple_mode, uint32 id) const; |
195 |
> |
|
196 |
> |
// Find maximum supported depth for given resolution ID |
197 |
> |
video_depth max_depth_of_resolution(uint32 id) const; |
198 |
> |
|
199 |
> |
// Get X/Y size of specified resolution |
200 |
> |
void get_size_of_resolution(uint32 id, uint32 &x, uint32 &y) const; |
201 |
> |
|
202 |
> |
// Set palette to 50% gray |
203 |
> |
void set_gray_palette(void); |
204 |
> |
|
205 |
> |
// Load gamma-corrected black-to-white ramp to palette for direct-color mode |
206 |
> |
void load_ramp_palette(void); |
207 |
> |
|
208 |
> |
// Allocate gamma table of specified size |
209 |
> |
bool allocate_gamma_table(int size); |
210 |
> |
|
211 |
> |
// Set gamma table (0 = build linear ramp) |
212 |
> |
bool set_gamma_table(uint32 user_table); |
213 |
> |
|
214 |
> |
// Switch video mode |
215 |
> |
void switch_mode(vector<video_mode>::const_iterator it, uint32 param, uint32 dce); |
216 |
> |
|
217 |
> |
uint8 slot_id; // NuBus slot ID number |
218 |
> |
static uint8 next_slot_id; // Next available slot ID |
219 |
> |
|
220 |
> |
uint8 palette[256 * 3]; // Color palette, 256 entries, RGB |
221 |
> |
|
222 |
> |
bool luminance_mapping; // Luminance mapping on/off |
223 |
> |
bool interrupts_enabled; // VBL interrupts on/off |
224 |
> |
bool dm_present; // We received a GetVideoParameters call, so the Display Manager seems to be present |
225 |
> |
|
226 |
> |
uint32 gamma_table; // Mac address of gamma table |
227 |
> |
int alloc_gamma_table_size; // Allocated size of gamma table |
228 |
> |
|
229 |
> |
uint16 current_apple_mode; // Currently selected depth/resolution |
230 |
> |
uint32 current_id; |
231 |
> |
uint16 preferred_apple_mode; // Preferred depth/resolution |
232 |
> |
uint32 preferred_id; |
233 |
> |
|
234 |
> |
uint32 slot_param; // Mac address of Slot Manager parameter block |
235 |
> |
|
236 |
> |
// For compatibility reasons with older (pre-Display Manager) versions of |
237 |
> |
// MacOS, the Apple modes must start at 0x80 and be contiguous. Therefore |
238 |
> |
// we maintain an array to map the depth codes to the corresponding Apple |
239 |
> |
// mode. |
240 |
> |
uint16 apple_mode_for_depth[6]; |
241 |
> |
|
242 |
> |
// The following functions are implemented by platform-specific code |
243 |
> |
public: |
244 |
> |
|
245 |
> |
// Called by the video driver to switch the video mode on this display |
246 |
> |
// (must call set_mac_frame_base()) |
247 |
> |
virtual void switch_to_current_mode(void) = 0; |
248 |
> |
|
249 |
> |
// Called by the video driver to set the color palette (in indexed modes) |
250 |
> |
// or the gamma table (in direct modes) |
251 |
> |
virtual void set_palette(uint8 *pal, int num) = 0; |
252 |
|
}; |
253 |
|
|
254 |
< |
extern monitor_desc VideoMonitor; // Description of the main monitor, set by VideoInit() |
254 |
> |
// Vector of pointers to available monitor descriptions, filled by VideoInit() |
255 |
> |
extern vector<monitor_desc *> VideoMonitors; |
256 |
> |
|
257 |
|
|
258 |
|
extern int16 VideoDriverOpen(uint32 pb, uint32 dce); |
259 |
|
extern int16 VideoDriverControl(uint32 pb, uint32 dce); |
260 |
|
extern int16 VideoDriverStatus(uint32 pb, uint32 dce); |
261 |
|
|
262 |
+ |
|
263 |
|
// System specific and internal functions/data |
264 |
|
extern bool VideoInit(bool classic); |
265 |
|
extern void VideoExit(void); |
269 |
|
extern void VideoInterrupt(void); |
270 |
|
extern void VideoRefresh(void); |
271 |
|
|
89 |
– |
extern void video_switch_to_mode(const video_mode &mode); |
90 |
– |
extern void video_set_palette(uint8 *pal); |
91 |
– |
|
272 |
|
#endif |