1 |
cebix |
1.1 |
/* |
2 |
|
|
* video_screen.h - Full screen video modes |
3 |
|
|
* |
4 |
cebix |
1.2 |
* SheepShaver (C) 1997-2004 Marc Hellwig and Christian Bauer |
5 |
cebix |
1.1 |
* |
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 |
8 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
9 |
|
|
* (at your option) any later version. |
10 |
|
|
* |
11 |
|
|
* This program is distributed in the hope that it will be useful, |
12 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
|
|
* GNU General Public License for more details. |
15 |
|
|
* |
16 |
|
|
* You should have received a copy of the GNU General Public License |
17 |
|
|
* along with this program; if not, write to the Free Software |
18 |
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 |
|
|
*/ |
20 |
|
|
|
21 |
|
|
|
22 |
|
|
static bool drawing_enable = false; // This flag indicated if the access to the screen is allowed |
23 |
|
|
static int page_num; // Index of the currently displayed buffer |
24 |
|
|
|
25 |
|
|
|
26 |
|
|
// Blitter functions |
27 |
|
|
typedef void (*bitblt_ptr)(int32, int32, int32, int32, int32, int32); |
28 |
|
|
static bitblt_ptr bitblt_hook; |
29 |
|
|
typedef void (*fillrect8_ptr)(int32, int32, int32, int32, uint8); |
30 |
|
|
static fillrect8_ptr fillrect8_hook; |
31 |
|
|
typedef void (*fillrect32_ptr)(int32, int32, int32, int32, uint32); |
32 |
|
|
static fillrect32_ptr fillrect32_hook; |
33 |
|
|
typedef void (*invrect_ptr)(int32, int32, int32, int32); |
34 |
|
|
static invrect_ptr invrect_hook; |
35 |
|
|
typedef void (*sync_ptr)(void); |
36 |
|
|
static sync_ptr sync_hook; |
37 |
|
|
|
38 |
|
|
|
39 |
|
|
class MacScreen : public BWindowScreen { |
40 |
|
|
public: |
41 |
|
|
MacScreen(const char *name, uint32 space); |
42 |
|
|
virtual ~MacScreen(); |
43 |
|
|
virtual void Quit(void); |
44 |
|
|
virtual void ScreenConnected(bool active); |
45 |
|
|
|
46 |
|
|
bool palette_changed; |
47 |
|
|
|
48 |
|
|
private: |
49 |
|
|
static status_t tick_func(void *arg); |
50 |
|
|
|
51 |
|
|
BView *view; // Main view for GetMouse() |
52 |
|
|
|
53 |
|
|
uint8 *frame_backup; // Frame buffer backup when switching from/to different workspace |
54 |
|
|
bool quitting; // Flag for ScreenConnected: We are quitting, don't pause emulator thread |
55 |
|
|
bool first; // Flag for ScreenConnected: This is the first time we become active |
56 |
|
|
|
57 |
|
|
thread_id tick_thread; |
58 |
|
|
bool tick_thread_active; |
59 |
|
|
}; |
60 |
|
|
|
61 |
|
|
|
62 |
|
|
// Pointer to our screen |
63 |
|
|
static MacScreen *the_screen = NULL; |
64 |
|
|
|
65 |
|
|
// Error code from BWindowScreen constructor |
66 |
|
|
static status_t screen_error; |
67 |
|
|
|
68 |
|
|
// to enable debugger mode. |
69 |
|
|
#define SCREEN_DEBUG false |
70 |
|
|
|
71 |
|
|
|
72 |
|
|
/* |
73 |
|
|
* Screen constructor |
74 |
|
|
*/ |
75 |
|
|
|
76 |
|
|
MacScreen::MacScreen(const char *name, uint32 space) : BWindowScreen(name, space, &screen_error, SCREEN_DEBUG), tick_thread(-1) |
77 |
|
|
{ |
78 |
|
|
D(bug("Screen constructor\n")); |
79 |
|
|
|
80 |
|
|
// Set all variables |
81 |
|
|
frame_backup = NULL; |
82 |
|
|
palette_changed = false; |
83 |
|
|
quitting = false; |
84 |
|
|
first = true; |
85 |
|
|
drawing_enable = false; |
86 |
|
|
ADBSetRelMouseMode(true); |
87 |
|
|
|
88 |
|
|
// Create view to poll the mouse |
89 |
|
|
view = new BView (BRect(0,0,VModes[cur_mode].viXsize-1,VModes[cur_mode].viYsize-1),NULL,B_FOLLOW_NONE,0); |
90 |
|
|
AddChild(view); |
91 |
|
|
|
92 |
|
|
// Start 60Hz interrupt |
93 |
|
|
tick_thread_active = true; |
94 |
|
|
tick_thread = spawn_thread(tick_func, "Polling sucks...", B_DISPLAY_PRIORITY, this); |
95 |
|
|
RegisterThread(tick_thread); |
96 |
|
|
resume_thread(tick_thread); |
97 |
|
|
|
98 |
|
|
// Add filter for keyboard and mouse events |
99 |
|
|
BMessageFilter *filter = new BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, filter_func); |
100 |
|
|
AddCommonFilter(filter); |
101 |
|
|
D(bug("Screen constructor done\n")); |
102 |
|
|
} |
103 |
|
|
|
104 |
|
|
|
105 |
|
|
/* |
106 |
|
|
* Screen destructor |
107 |
|
|
*/ |
108 |
|
|
|
109 |
|
|
MacScreen::~MacScreen() |
110 |
|
|
{ |
111 |
|
|
D(bug("Screen destructor, quitting tick thread\n")); |
112 |
|
|
|
113 |
|
|
// Stop 60Hz interrupt |
114 |
|
|
if (tick_thread > 0) { |
115 |
|
|
status_t l; |
116 |
|
|
tick_thread_active = false; |
117 |
|
|
while (wait_for_thread(tick_thread, &l) == B_INTERRUPTED) ; |
118 |
|
|
} |
119 |
|
|
D(bug("tick thread quit\n")); |
120 |
|
|
|
121 |
|
|
// Tell the emulator that we're done |
122 |
|
|
the_screen = NULL; |
123 |
|
|
D(bug("Screen destructor done\n")); |
124 |
|
|
} |
125 |
|
|
|
126 |
|
|
|
127 |
|
|
/* |
128 |
|
|
* Screen closed |
129 |
|
|
*/ |
130 |
|
|
|
131 |
|
|
void MacScreen::Quit(void) |
132 |
|
|
{ |
133 |
|
|
// Tell ScreenConnected() that we are quitting |
134 |
|
|
quitting = true; |
135 |
|
|
D(bug("MacScreen::Quit(), disconnecting\n")); |
136 |
|
|
Disconnect(); |
137 |
|
|
D(bug("disconnected\n")); |
138 |
|
|
BWindowScreen::Quit(); |
139 |
|
|
} |
140 |
|
|
|
141 |
|
|
|
142 |
|
|
/* |
143 |
|
|
* Screen connected/disconnected |
144 |
|
|
*/ |
145 |
|
|
|
146 |
|
|
void MacScreen::ScreenConnected(bool active) |
147 |
|
|
{ |
148 |
|
|
D(bug("ScreenConnected(%d)\n", active)); |
149 |
|
|
graphics_card_info *info = CardInfo(); |
150 |
|
|
D(bug(" card_info %p\n", info)); |
151 |
|
|
|
152 |
|
|
if (active) { |
153 |
|
|
|
154 |
|
|
// Read graphics parameters |
155 |
|
|
D(bug(" active\n")); |
156 |
|
|
screen_base = (uint32)info->frame_buffer; |
157 |
|
|
D(bug(" screen_base %p\n", screen_base)); |
158 |
|
|
VModes[cur_mode].viRowBytes = info->bytes_per_row; |
159 |
|
|
D(bug(" xmod %d\n", info->bytes_per_row)); |
160 |
|
|
|
161 |
|
|
// Get acceleration functions |
162 |
|
|
if (PrefsFindBool("gfxaccel")) { |
163 |
|
|
bitblt_hook = (bitblt_ptr)CardHookAt(7); |
164 |
|
|
D(bug(" bitblt_hook %p\n", bitblt_hook)); |
165 |
|
|
fillrect8_hook = (fillrect8_ptr)CardHookAt(5); |
166 |
|
|
D(bug(" fillrect8_hook %p\n", fillrect8_hook)); |
167 |
|
|
fillrect32_hook = (fillrect32_ptr)CardHookAt(6); |
168 |
|
|
D(bug(" fillrect32_hook %p\n", fillrect32_hook)); |
169 |
|
|
invrect_hook = (invrect_ptr)CardHookAt(11); |
170 |
|
|
D(bug(" invrect_hook %p\n", invrect_hook)); |
171 |
|
|
sync_hook = (sync_ptr)CardHookAt(10); |
172 |
|
|
D(bug(" sync_hook %p\n", sync_hook)); |
173 |
|
|
} else { |
174 |
|
|
bitblt_hook = NULL; |
175 |
|
|
fillrect8_hook = NULL; |
176 |
|
|
fillrect32_hook = NULL; |
177 |
|
|
invrect_hook = NULL; |
178 |
|
|
sync_hook = NULL; |
179 |
|
|
} |
180 |
|
|
|
181 |
|
|
// The first time we got the screen, we need to init the Window |
182 |
|
|
if (first) { |
183 |
|
|
D(bug(" first time\n")); |
184 |
|
|
first = false; |
185 |
|
|
page_num = 0; // current display : page 0 |
186 |
|
|
} else { // we get our screen back |
187 |
|
|
D(bug(" not first time\n")); |
188 |
|
|
// copy from backup bitmap to framebuffer |
189 |
|
|
memcpy((void *)screen_base, frame_backup, VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize); |
190 |
|
|
// delete backup bitmap |
191 |
|
|
delete[] frame_backup; |
192 |
|
|
frame_backup = NULL; |
193 |
|
|
// restore palette |
194 |
|
|
if (info->bits_per_pixel == 8) |
195 |
|
|
SetColorList(mac_pal); |
196 |
|
|
// restart emul thread |
197 |
|
|
release_sem(mac_os_lock); |
198 |
|
|
} |
199 |
|
|
|
200 |
|
|
// allow the drawing in the frame buffer |
201 |
|
|
D(bug(" enabling frame buffer access\n")); |
202 |
|
|
drawing_enable = true; |
203 |
|
|
video_activated = true; |
204 |
|
|
|
205 |
|
|
} else { |
206 |
|
|
|
207 |
|
|
drawing_enable = false; // stop drawing. |
208 |
|
|
video_activated = false; |
209 |
|
|
if (!quitting) { |
210 |
|
|
// stop emul thread |
211 |
|
|
acquire_sem(mac_os_lock); |
212 |
|
|
// create bitmap and store frame buffer into |
213 |
|
|
frame_backup = new uint8[VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize]; |
214 |
|
|
memcpy(frame_backup, (void *)screen_base, VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize); |
215 |
|
|
} |
216 |
|
|
} |
217 |
|
|
D(bug("ScreenConnected() done\n")); |
218 |
|
|
} |
219 |
|
|
|
220 |
|
|
|
221 |
|
|
/* |
222 |
|
|
* 60Hz interrupt routine |
223 |
|
|
*/ |
224 |
|
|
|
225 |
|
|
status_t MacScreen::tick_func(void *arg) |
226 |
|
|
{ |
227 |
|
|
MacScreen *obj = (MacScreen *)arg; |
228 |
|
|
while (obj->tick_thread_active) { |
229 |
|
|
|
230 |
|
|
// Wait |
231 |
|
|
snooze(16667); |
232 |
|
|
|
233 |
|
|
// Workspace activated? Then poll the mouse and change the palette if needed |
234 |
|
|
if (video_activated) { |
235 |
|
|
BPoint pt; |
236 |
|
|
uint32 button = 0; |
237 |
|
|
if (obj->LockWithTimeout(200000) == B_OK) { |
238 |
|
|
if (obj->palette_changed) { |
239 |
|
|
obj->palette_changed = false; |
240 |
|
|
obj->SetColorList(mac_pal); |
241 |
|
|
} |
242 |
|
|
obj->view->GetMouse(&pt, &button); |
243 |
|
|
obj->Unlock(); |
244 |
|
|
set_mouse_position(320, 240); |
245 |
|
|
ADBMouseMoved(int(pt.x) - 320, int(pt.y) - 240); |
246 |
|
|
if (button & B_PRIMARY_MOUSE_BUTTON) |
247 |
|
|
ADBMouseDown(0); |
248 |
|
|
if (!(button & B_PRIMARY_MOUSE_BUTTON)) |
249 |
|
|
ADBMouseUp(0); |
250 |
|
|
if (button & B_SECONDARY_MOUSE_BUTTON) |
251 |
|
|
ADBMouseDown(1); |
252 |
|
|
if (!(button & B_SECONDARY_MOUSE_BUTTON)) |
253 |
|
|
ADBMouseUp(1); |
254 |
|
|
if (button & B_TERTIARY_MOUSE_BUTTON) |
255 |
|
|
ADBMouseDown(2); |
256 |
|
|
if (!(button & B_TERTIARY_MOUSE_BUTTON)) |
257 |
|
|
ADBMouseUp(2); |
258 |
|
|
} |
259 |
|
|
} |
260 |
|
|
} |
261 |
|
|
return 0; |
262 |
|
|
} |