28 |
|
#include "main.h" |
29 |
|
|
30 |
|
|
31 |
+ |
#define BIT_BANG 0 |
32 |
+ |
#define MGA_HACK 1 |
33 |
+ |
|
34 |
+ |
|
35 |
|
// Window thread messages |
36 |
|
const uint32 MSG_REDRAW = 1; |
37 |
|
|
88 |
|
3, 4, 4, 5, 5, 6, 6, 8+0, |
89 |
|
0x26,0x22,0x2a, 0, 7, -1, 7, -1, |
90 |
|
|
91 |
< |
7, 8+0, 0, 0,0x30, -1, 7, 7, |
91 |
> |
0x30, 8+0, 0, 0,0x30, -1, 7, 7, |
92 |
|
-1, -1, -1, -1, -1, -1, -1, -1, |
93 |
|
|
94 |
|
-1, -1, -1, -1, -1, -1, -1, -1, |
145 |
|
class SpeedoView; |
146 |
|
class LEDView; |
147 |
|
|
148 |
< |
class C64Window : public BWindow { |
148 |
> |
class C64Window : public BDirectWindow { |
149 |
|
public: |
150 |
|
C64Window(); |
151 |
|
|
152 |
|
virtual bool QuitRequested(void); |
153 |
|
virtual void MessageReceived(BMessage *msg); |
154 |
+ |
virtual void DirectConnected(direct_buffer_info *info); |
155 |
|
|
156 |
|
BBitmap *TheBitmap[2]; |
157 |
|
SpeedoView *Speedometer; |
158 |
|
LEDView *LED[4]; |
159 |
|
|
160 |
+ |
#if BIT_BANG |
161 |
+ |
uint8 *bits; |
162 |
+ |
int bytes_per_row; |
163 |
+ |
#endif |
164 |
+ |
|
165 |
|
private: |
166 |
|
BitmapView *main_view; |
167 |
|
}; |
176 |
|
C64Screen(C64Display *display) : BWindowScreen("Frodo", B_8_BIT_640x480, &error), the_display(display) |
177 |
|
{ |
178 |
|
Lock(); |
179 |
< |
BitmapView *main_view = new BitmapView(Bounds(), NULL); |
179 |
> |
TheBitmap = new BBitmap(DisplayFrame, B_COLOR_8_BIT); |
180 |
> |
main_view = new BitmapView(Bounds(), TheBitmap); |
181 |
|
AddChild(main_view); |
182 |
|
main_view->MakeFocus(); |
183 |
|
Connected = false; |
184 |
+ |
first_connected = true; |
185 |
+ |
#if MGA_HACK |
186 |
+ |
mga_ready = false; |
187 |
+ |
#endif |
188 |
|
Unlock(); |
189 |
|
} |
190 |
+ |
~C64Screen() |
191 |
+ |
{ |
192 |
+ |
delete TheBitmap; |
193 |
+ |
} |
194 |
|
|
195 |
|
virtual void ScreenConnected(bool active); |
196 |
|
virtual void DispatchMessage(BMessage *msg, BHandler *handler); |
201 |
|
bool Connected; // Flag: screen connected |
202 |
|
int Speed; |
203 |
|
char SpeedoStr[16]; // Speedometer value converted to a string |
204 |
+ |
BBitmap *TheBitmap; |
205 |
|
|
206 |
|
private: |
207 |
|
C64Display *the_display; |
208 |
+ |
BitmapView *main_view; |
209 |
+ |
bool first_connected; |
210 |
|
status_t error; |
211 |
+ |
|
212 |
+ |
#if MGA_HACK |
213 |
+ |
area_id mga_clone_area; |
214 |
+ |
volatile uint8 *isa_io; |
215 |
+ |
bool mga_ready; |
216 |
+ |
|
217 |
+ |
void CRTC_out(int reg, uint8 val) {isa_io[0x3d4] = reg; __eieio(); isa_io[0x3d5] = val; __eieio();} |
218 |
+ |
uint8 CRTC_in(int reg) {isa_io[0x3d4] = reg; __eieio(); return isa_io[0x3d5];} |
219 |
+ |
void SEQ_out(int reg, uint8 val) {isa_io[0x3c4] = reg; __eieio(); isa_io[0x3c5] = val; __eieio();} |
220 |
+ |
uint8 SEQ_in(int reg) {isa_io[0x3c4] = reg; __eieio(); return isa_io[0x3c5];} |
221 |
+ |
void GDC_out(int reg, uint8 val) {isa_io[0x3ce] = reg; __eieio(); isa_io[0x3cf] = val; __eieio();} |
222 |
+ |
uint8 GDC_in(int reg) {isa_io[0x3ce] = reg; __eieio(); return isa_io[0x3cf];} |
223 |
+ |
void ATC_out(int reg, uint8 val) {isa_io[0x3c0] = reg; __eieio(); isa_io[0x3c0] = val; __eieio();} |
224 |
+ |
#endif |
225 |
|
}; |
226 |
|
|
227 |
|
|
349 |
|
the_screen->DrawLED(i, led_state[i]); |
350 |
|
the_screen->DrawSpeedometer(); |
351 |
|
|
352 |
+ |
// Update C64 display in dobule scan mode |
353 |
+ |
if (ThePrefs.DoubleScan) { |
354 |
+ |
uint8 *src = (uint8 *)the_screen->TheBitmap->Bits(); |
355 |
+ |
uint32 src_xmod = the_screen->TheBitmap->BytesPerRow(); |
356 |
+ |
src += src_xmod * 16 + 32; |
357 |
+ |
uint8 *dest = (uint8 *)the_screen->CardInfo()->frame_buffer; |
358 |
+ |
uint32 dest_xmod = the_screen->CardInfo()->bytes_per_row; |
359 |
+ |
#ifdef __POWERPC__ |
360 |
+ |
double tmp[1]; |
361 |
+ |
for (int y=0; y<240; y++) { |
362 |
+ |
uint32 *p = (uint32 *)src - 1; |
363 |
+ |
double *q1 = (double *)dest - 1; |
364 |
+ |
double *q2 = q1 + dest_xmod / sizeof(double); |
365 |
+ |
for (int x=0; x<80; x++) { |
366 |
+ |
uint32 val = *(++p); |
367 |
+ |
uint8 *r = (uint8 *)&tmp[1]; |
368 |
+ |
*(--r) = val; |
369 |
+ |
*(--r) = val; |
370 |
+ |
val >>= 8; |
371 |
+ |
*(--r) = val; |
372 |
+ |
*(--r) = val; |
373 |
+ |
val >>= 8; |
374 |
+ |
*(--r) = val; |
375 |
+ |
*(--r) = val; |
376 |
+ |
val >>= 8; |
377 |
+ |
*(--r) = val; |
378 |
+ |
*(--r) = val; |
379 |
+ |
double tmp2 = tmp[0]; |
380 |
+ |
*(++q1) = tmp2; |
381 |
+ |
*(++q2) = tmp2; |
382 |
+ |
} |
383 |
+ |
src += src_xmod; |
384 |
+ |
dest += dest_xmod * 2; |
385 |
+ |
} |
386 |
+ |
#else |
387 |
+ |
for (int y=0; y<240; y++) { |
388 |
+ |
uint32 *p = (uint32 *)src; |
389 |
+ |
uint32 *q1 = (uint32 *)dest; |
390 |
+ |
uint32 *q2 = q1 + dest_xmod / sizeof(uint32); |
391 |
+ |
for (int x=0; x<80; x++) { |
392 |
+ |
uint32 val = *p++; |
393 |
+ |
uint32 tmp = val & 0x000000ff; |
394 |
+ |
tmp |= (val << 8) & 0x0000ff00; |
395 |
+ |
tmp |= (val << 8) & 0x00ff0000; |
396 |
+ |
tmp |= (val << 16) & 0xff000000; |
397 |
+ |
*q1++ = tmp; |
398 |
+ |
*q2++ = tmp; |
399 |
+ |
tmp = (val >> 16) & 0x000000ff; |
400 |
+ |
tmp |= (val >> 8) & 0x0000ff00; |
401 |
+ |
tmp |= (val >> 8) & 0x00ff0000; |
402 |
+ |
tmp |= val & 0xff000000; |
403 |
+ |
*q1++ = tmp; |
404 |
+ |
*q2++ = tmp; |
405 |
+ |
} |
406 |
+ |
src += src_xmod; |
407 |
+ |
dest += dest_xmod * 2; |
408 |
+ |
} |
409 |
+ |
#endif |
410 |
+ |
} |
411 |
+ |
|
412 |
|
} else { |
413 |
|
|
414 |
+ |
#if !BIT_BANG |
415 |
|
// Update C64 display |
416 |
|
BMessage msg(MSG_REDRAW); |
417 |
|
msg.AddInt32("bitmap", draw_bitmap); |
418 |
|
the_window->PostMessage(&msg); |
419 |
|
draw_bitmap ^= 1; |
420 |
+ |
#endif |
421 |
|
|
422 |
|
// Update LEDs |
423 |
|
for (int i=0; i<4; i++) |
449 |
|
|
450 |
|
uint8 *C64Display::BitmapBase(void) |
451 |
|
{ |
452 |
< |
if (using_screen) |
453 |
< |
return (uint8 *)the_screen->CardInfo()->frame_buffer; |
454 |
< |
else |
452 |
> |
if (using_screen) { |
453 |
> |
if (ThePrefs.DoubleScan) |
454 |
> |
return (uint8 *)the_screen->TheBitmap->Bits(); |
455 |
> |
else |
456 |
> |
return (uint8 *)the_screen->CardInfo()->frame_buffer; |
457 |
> |
} else |
458 |
> |
#if BIT_BANG |
459 |
> |
return (uint8 *)the_window->bits; |
460 |
> |
#else |
461 |
|
return (uint8 *)the_window->TheBitmap[draw_bitmap]->Bits(); |
462 |
+ |
#endif |
463 |
|
} |
464 |
|
|
465 |
|
|
469 |
|
|
470 |
|
int C64Display::BitmapXMod(void) |
471 |
|
{ |
472 |
< |
if (using_screen) |
473 |
< |
return the_screen->CardInfo()->bytes_per_row; |
474 |
< |
else |
472 |
> |
if (using_screen) { |
473 |
> |
if (ThePrefs.DoubleScan) |
474 |
> |
return the_screen->TheBitmap->BytesPerRow(); |
475 |
> |
else |
476 |
> |
return the_screen->CardInfo()->bytes_per_row; |
477 |
> |
} else |
478 |
> |
#if BIT_BANG |
479 |
> |
return the_window->bytes_per_row; |
480 |
> |
#else |
481 |
|
return the_window->TheBitmap[draw_bitmap]->BytesPerRow(); |
482 |
+ |
#endif |
483 |
|
} |
484 |
|
|
485 |
|
|
611 |
|
* Window constructor |
612 |
|
*/ |
613 |
|
|
614 |
< |
C64Window::C64Window() : BWindow(WindowFrame, "Frodo", B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE) |
614 |
> |
C64Window::C64Window() : BDirectWindow(WindowFrame, "Frodo", B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE) |
615 |
|
{ |
616 |
|
// Move window to right position |
617 |
|
Lock(); |
636 |
|
bar->AddItem(menu); |
637 |
|
AddChild(bar); |
638 |
|
SetKeyMenuBar(bar); |
639 |
< |
int mbar_height = bar->Frame().bottom + 1; |
639 |
> |
int mbar_height = int(bar->Frame().bottom) + 1; |
640 |
|
|
641 |
|
// Resize window to fit menu bar |
642 |
|
ResizeBy(0, mbar_height); |
697 |
|
switch (msg->what) { |
698 |
|
case MSG_REDRAW: // Redraw bitmap |
699 |
|
MessageQueue()->Lock(); |
700 |
< |
while ((msg2 = MessageQueue()->FindMessage(MSG_REDRAW, 0)) != NULL) |
700 |
> |
while ((msg2 = MessageQueue()->FindMessage(MSG_REDRAW, 0)) != NULL) { |
701 |
|
MessageQueue()->RemoveMessage(msg2); |
702 |
+ |
delete msg2; |
703 |
+ |
} |
704 |
|
MessageQueue()->Unlock(); |
705 |
|
main_view->ChangeBitmap(TheBitmap[msg->FindInt32("bitmap")]); |
706 |
|
Lock(); |
715 |
|
|
716 |
|
|
717 |
|
/* |
718 |
+ |
* Window connected/disconnected |
719 |
+ |
*/ |
720 |
+ |
|
721 |
+ |
void C64Window::DirectConnected(direct_buffer_info *info) |
722 |
+ |
{ |
723 |
+ |
#if BIT_BANG |
724 |
+ |
switch (info->buffer_state & B_DIRECT_MODE_MASK) { |
725 |
+ |
case B_DIRECT_STOP: |
726 |
+ |
// acquire_sem(drawing_sem); |
727 |
+ |
break; |
728 |
+ |
case B_DIRECT_MODIFY: |
729 |
+ |
// acquire_sem(drawing_sem); |
730 |
+ |
case B_DIRECT_START: |
731 |
+ |
bits = ((uint8 *)info->bits + info->window_bounds.top * info->bytes_per_row + info->window_bounds.left * info->bits_per_pixel / 8); |
732 |
+ |
bytes_per_row = info->bytes_per_row; |
733 |
+ |
// release_sem(drawing_sem); |
734 |
+ |
break; |
735 |
+ |
} |
736 |
+ |
#endif |
737 |
+ |
} |
738 |
+ |
|
739 |
+ |
|
740 |
+ |
/* |
741 |
|
* Workspace activated/deactivated |
742 |
|
*/ |
743 |
|
|
744 |
|
void C64Screen::ScreenConnected(bool active) |
745 |
|
{ |
746 |
|
if (active) { |
747 |
+ |
if (first_connected) { |
748 |
+ |
first_connected = false; |
749 |
+ |
|
750 |
+ |
#if MGA_HACK |
751 |
+ |
mga_clone_area = -1; |
752 |
+ |
|
753 |
+ |
// Construct register area name |
754 |
+ |
char mga_area_name[64]; |
755 |
+ |
int bus = 0, device = 13, function = 0; |
756 |
+ |
sprintf(mga_area_name, "102B_0519_%02X%02X%02X regs", bus, device, function); |
757 |
+ |
|
758 |
+ |
// Find MGA register area |
759 |
+ |
area_id mga_area = find_area(mga_area_name); |
760 |
+ |
if (mga_area > 0) { |
761 |
+ |
|
762 |
+ |
// Clone area, remove write protection |
763 |
+ |
volatile uint8 *mga_io; |
764 |
+ |
mga_clone_area = clone_area("mga registers", (void **)&mga_io, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, mga_area); |
765 |
+ |
if (mga_clone_area > 0) { |
766 |
+ |
isa_io = mga_io + 0x1c00; |
767 |
+ |
mga_ready = true; |
768 |
+ |
} |
769 |
+ |
} |
770 |
+ |
#endif |
771 |
+ |
} |
772 |
+ |
|
773 |
+ |
#if MGA_HACK |
774 |
+ |
if (mga_ready) { |
775 |
+ |
CRTC_out(0x09, 1); // Enable double scan |
776 |
+ |
int a = 4 * 640; |
777 |
+ |
CRTC_out(0x0c, a >> 8); // Center screen vertically |
778 |
+ |
CRTC_out(0x0d, a); |
779 |
+ |
// defaults: |
780 |
+ |
// total 0x67 |
781 |
+ |
// display end 0x4f |
782 |
+ |
// blank start 0x4f |
783 |
+ |
// blank end 2b |
784 |
+ |
// sync start 0x53 |
785 |
+ |
// sync end 1f |
786 |
+ |
CRTC_out(0x00, 0x3f); // Horizontal timing |
787 |
+ |
CRTC_out(0x01, 0x2f); |
788 |
+ |
CRTC_out(0x02, 0x2f); |
789 |
+ |
CRTC_out(0x03, 0x83); |
790 |
+ |
CRTC_out(0x04, 0x32); |
791 |
+ |
CRTC_out(0x05, 0x1a); |
792 |
+ |
} |
793 |
+ |
#endif |
794 |
+ |
|
795 |
|
FillRect(0, 0, 639, 479, 0); // Clear screen |
796 |
|
the_display->TheC64->Resume(); |
797 |
|
Connected = true; |
842 |
|
|
843 |
|
void C64Screen::DrawLED(int i, int state) |
844 |
|
{ |
845 |
+ |
int maxy; |
846 |
+ |
if (ThePrefs.DoubleScan) |
847 |
+ |
maxy = 480; |
848 |
+ |
else |
849 |
+ |
maxy = DISPLAY_Y; |
850 |
+ |
|
851 |
|
switch (state) { |
852 |
|
case LED_ON: |
853 |
< |
FillRect(10+i*20, DISPLAY_Y-20, 20+i*20, DISPLAY_Y-12, 54); |
853 |
> |
FillRect(10+i*20, maxy-20, 20+i*20, maxy-12, 54); |
854 |
|
break; |
855 |
|
case LED_ERROR_ON: |
856 |
< |
FillRect(10+i*20, DISPLAY_Y-20, 20+i*20, DISPLAY_Y-12, 44); |
856 |
> |
FillRect(10+i*20, maxy-20, 20+i*20, maxy-12, 44); |
857 |
|
break; |
858 |
|
} |
859 |
|
} |
880 |
|
void C64Screen::DrawSpeedometer() |
881 |
|
{ |
882 |
|
// Don't display speedometer if we're running at about 100% |
883 |
< |
if (Speed >= 99 && Speed <= 101) |
883 |
> |
if (Speed >= 50 && Speed <= 101) |
884 |
|
return; |
885 |
|
|
886 |
+ |
int maxx, maxy; |
887 |
+ |
if (ThePrefs.DoubleScan) { |
888 |
+ |
maxx = 640; |
889 |
+ |
maxy = 480; |
890 |
+ |
} else { |
891 |
+ |
maxx = DISPLAY_X; |
892 |
+ |
maxy = DISPLAY_Y; |
893 |
+ |
} |
894 |
+ |
|
895 |
|
char *s = SpeedoStr; |
896 |
|
char c; |
897 |
|
long xmod = CardInfo()->bytes_per_row; |
898 |
< |
uint8 *p = (uint8 *)CardInfo()->frame_buffer + DISPLAY_X - 8*8 + (DISPLAY_Y-20) * xmod; |
899 |
< |
while (c = *s++) { |
898 |
> |
uint8 *p = (uint8 *)CardInfo()->frame_buffer + maxx - 8*8 + (maxy-20) * xmod; |
899 |
> |
while ((c = *s++) != 0) { |
900 |
|
if (c == ' ') |
901 |
|
continue; |
902 |
|
if (c == '%') |
929 |
|
uint8 *p = (uint8 *)CardInfo()->frame_buffer + y1 * xmod + x1; |
930 |
|
int n = x2 - x1 + 1; |
931 |
|
for(int y=y1; y<=y2; y++) { |
932 |
+ |
#ifdef __POWERPC__ |
933 |
|
memset_nc(p, color, n); |
934 |
+ |
#else |
935 |
+ |
memset(p, color, n); |
936 |
+ |
#endif |
937 |
|
p += xmod; |
938 |
|
} |
939 |
|
} |