--- SheepShaver/src/video.cpp 2003/12/04 17:26:35 1.4 +++ SheepShaver/src/video.cpp 2008/01/01 09:47:38 1.15 @@ -1,7 +1,7 @@ /* * video.cpp - Video/graphics emulation * - * SheepShaver (C) 1997-2002 Marc Hellwig and Christian Bauer + * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -74,15 +74,15 @@ static long save_conf_mode = APPLE_8_BIT // Function pointers of imported functions typedef int16 (*iocic_ptr)(void *, int16); static uint32 iocic_tvect = 0; -static inline int16 IOCommandIsComplete(void *arg1, int16 arg2) +static inline int16 IOCommandIsComplete(uintptr arg1, int16 arg2) { - return (int16)CallMacOS2(iocic_ptr, iocic_tvect, arg1, arg2); + return (int16)CallMacOS2(iocic_ptr, iocic_tvect, (void *)arg1, arg2); } typedef int16 (*vslnewis_ptr)(void *, uint32, uint32 *); static uint32 vslnewis_tvect = 0; -static inline int16 VSLNewInterruptService(void *arg1, uint32 arg2, uint32 *arg3) +static inline int16 VSLNewInterruptService(uintptr arg1, uint32 arg2, uintptr arg3) { - return (int16)CallMacOS3(vslnewis_ptr, vslnewis_tvect, arg1, arg2, arg3); + return (int16)CallMacOS3(vslnewis_ptr, vslnewis_tvect, (void *)arg1, arg2, (uint32 *)arg3); } typedef int16 (*vsldisposeis_ptr)(uint32); static uint32 vsldisposeis_tvect = 0; @@ -98,9 +98,9 @@ int16 VSLDoInterruptService(uint32 arg1) } typedef void (*nqdmisc_ptr)(uint32, void *); static uint32 nqdmisc_tvect = 0; -void NQDMisc(uint32 arg1, void *arg2) +void NQDMisc(uint32 arg1, uintptr arg2) { - CallMacOS2(nqdmisc_ptr, nqdmisc_tvect, arg1, arg2); + CallMacOS2(nqdmisc_ptr, nqdmisc_tvect, arg1, (void *)arg2); } @@ -156,20 +156,20 @@ static int16 VideoOpen(uint32 pb, VidLoc csSave->saveMode = VModes[cur_mode].viAppleMode; csSave->savePage = 0; csSave->saveVidParms = 0; // Add the right table - csSave->gammaTable = NULL; // No gamma table yet - csSave->maxGammaTableSize = 0; csSave->luminanceMapping = false; csSave->cursorX = 0; csSave->cursorY = 0; csSave->cursorVisible = 0; csSave->cursorSet = 0; - // Activate default gamma table + // Find and set default gamma table + csSave->gammaTable = 0; + csSave->maxGammaTableSize = 0; set_gamma(csSave, 0); // Install and activate interrupt service SheepVar32 theServiceID = 0; - VSLNewInterruptService(csSave->regEntryID, FOURCC('v','b','l',' '), (uint32 *)theServiceID.addr()); + VSLNewInterruptService(csSave->regEntryID, FOURCC('v','b','l',' '), theServiceID.addr()); csSave->vslServiceID = theServiceID.value(); D(bug(" Interrupt ServiceID %08lx\n", csSave->vslServiceID)); csSave->interruptsEnabled = true; @@ -182,82 +182,68 @@ static int16 VideoOpen(uint32 pb, VidLoc * Video driver control routine */ +static bool allocate_gamma_table(VidLocals *csSave, uint32 size) +{ + if (size > csSave->maxGammaTableSize) { + if (csSave->gammaTable) { + Mac_sysfree(csSave->gammaTable); + csSave->gammaTable = 0; + csSave->maxGammaTableSize = 0; + } + if ((csSave->gammaTable = Mac_sysalloc(size)) == 0) + return false; + csSave->maxGammaTableSize = size; + } + return true; +} + static int16 set_gamma(VidLocals *csSave, uint32 gamma) { - GammaTbl *clientGamma = (GammaTbl *)gamma; - GammaTbl *gammaTable = csSave->gammaTable; + return paramErr; - if (clientGamma == NULL) { + if (gamma == 0) { // Build linear ramp, 256 entries - // No gamma table supplied, build linear ramp - uint32 linearRampSize = sizeof(GammaTbl) + 256 - 2; - uint8 *correctionData; - - // Allocate new gamma table if existing gamma table is smaller than required. - if (linearRampSize > csSave->maxGammaTableSize) { - delete[] csSave->gammaTable; - csSave->gammaTable = (GammaTbl *)new uint8[linearRampSize]; - csSave->maxGammaTableSize = linearRampSize; - gammaTable = csSave->gammaTable; - } - - gammaTable->gVersion = 0; // A version 0 style of the GammaTbl structure - gammaTable->gType = 0; // Frame buffer hardware invariant - gammaTable->gFormulaSize = 0; // No formula data, just correction data - gammaTable->gChanCnt = 1; // Apply same correction to Red, Green, & Blue - gammaTable->gDataCnt = 256; // gDataCnt == 2^^gDataWidth - gammaTable->gDataWidth = 8; // 8 bits of significant data per entry - - // Find the starting address of the correction data. This can be computed by starting at - // the address of gFormula[0] and adding the gFormulaSize. - correctionData = (uint8 *)((uint32)&gammaTable->gFormulaData[0] + gammaTable->gFormulaSize); + // Allocate new table, if necessary + if (!allocate_gamma_table(csSave, SIZEOF_GammaTbl + 256)) + return memFullErr; + + // Initialize header + WriteMacInt16(csSave->gammaTable + gVersion, 0); // A version 0 style of the GammaTbl structure + WriteMacInt16(csSave->gammaTable + gType, 0); // Frame buffer hardware invariant + WriteMacInt16(csSave->gammaTable + gFormulaSize, 0); // No formula data, just correction data + WriteMacInt16(csSave->gammaTable + gChanCnt, 1); // Apply same correction to Red, Green, & Blue + WriteMacInt16(csSave->gammaTable + gDataCnt, 256); // gDataCnt == 2^^gDataWidth + WriteMacInt16(csSave->gammaTable + gDataWidth, 8); // 8 bits of significant data per entry // Build the linear ramp - for (int i=0; igDataCnt; i++) - *correctionData++ = i; + uint32 p = csSave->gammaTable + gFormulaData; + for (int i=0; i<256; i++) + WriteMacInt8(p + i, i); - } else { + } else { // User-supplied gamma table - // User supplied a gamma table, so make sure it is a valid one - if (clientGamma->gVersion != 0) + // Validate header + if (ReadMacInt16(gamma + gVersion) != 0) return paramErr; - if (clientGamma->gType != 0) + if (ReadMacInt16(gamma + gType) != 0) return paramErr; - if ((clientGamma->gChanCnt != 1) && (clientGamma->gChanCnt != 3)) + int chan_cnt = ReadMacInt16(gamma + gChanCnt); + if (chan_cnt != 1 && chan_cnt != 3) return paramErr; - if (clientGamma->gDataWidth > 8) + int data_width = ReadMacInt16(gamma + gDataWidth); + if (data_width > 8) return paramErr; - if (clientGamma->gDataCnt != (1 << clientGamma->gDataWidth)) + int data_cnt = ReadMacInt16(gamma + gDataWidth); + if (data_cnt != (1 << data_width)) return paramErr; - uint32 tableSize = sizeof(GammaTbl) // fixed size header - + clientGamma->gFormulaSize // add formula size - + clientGamma->gChanCnt * clientGamma->gDataCnt // assume 1 byte/entry - - 2; // correct gFormulaData[0] counted twice - - // Allocate new gamma table if existing gamma table is smaller than required. - if (tableSize > csSave->maxGammaTableSize) { - delete[] csSave->gammaTable; - csSave->gammaTable = (GammaTbl *)new uint8[tableSize]; - csSave->maxGammaTableSize = tableSize; - gammaTable = csSave->gammaTable; - } + // Allocate new table, if necessary + int size = SIZEOF_GammaTbl + ReadMacInt16(gamma + gFormulaSize) + chan_cnt * data_cnt; + if (!allocate_gamma_table(csSave, size)) + return memFullErr; - // Copy gamma table header - *gammaTable = *clientGamma; - - // Copy the formula data (if any) - uint8 *newData = (uint8 *)&gammaTable->gFormulaData[0]; // Point to newGamma's formula data - uint8 *clientData = (uint8 *)&clientGamma->gFormulaData[0]; // Point to clientGamma's formula data - for (int i=0; igFormulaSize; i++) - *newData++ = *clientData++; - - // Copy the correction data. Convientiently, after copying the formula data, the 'newData' - // pointer and the 'clientData' pointer are pointing to the their respective starting points - // of their correction data. - for (int i=0; igChanCnt; i++) - for (int j=0; jgDataCnt; j++) - *newData++ = *clientData++; + // Copy table + Mac2Mac_memcpy(csSave->gammaTable, gamma, size); } return noErr; } @@ -287,10 +273,10 @@ static int16 VideoControl(uint32 pb, Vid case cscSetEntries: { // SetEntries D(bug("SetEntries\n")); if (VModes[cur_mode].viAppleMode > APPLE_8_BIT) return controlErr; - ColorSpec *s_pal = (ColorSpec *)Mac2HostAddr(ReadMacInt32(param + csTable)); - int16 start = ReadMacInt16(param + csStart); - int16 count = ReadMacInt16(param + csCount); - if (s_pal == NULL || count > 256) return controlErr; + uint32 s_pal = ReadMacInt32(param + csTable); + uint16 start = ReadMacInt16(param + csStart); + uint16 count = ReadMacInt16(param + csCount); + if (s_pal == 0 || count > 256) return controlErr; // Preparations for gamma correction bool do_gamma = false; @@ -298,27 +284,37 @@ static int16 VideoControl(uint32 pb, Vid uint8 *green_gamma = NULL; uint8 *blue_gamma = NULL; int gamma_data_width = 0; - if (display_type == DIS_SCREEN && csSave->gammaTable != NULL) { // Windows are gamma-corrected by BeOS - do_gamma = true; - GammaTbl *gamma = csSave->gammaTable; - gamma_data_width = gamma->gDataWidth; - red_gamma = (uint8 *)&gamma->gFormulaData + gamma->gFormulaSize; - if (gamma->gChanCnt == 1) { - green_gamma = blue_gamma = red_gamma; - } else { - green_gamma = red_gamma + gamma->gDataCnt; - blue_gamma = red_gamma + 2 * gamma->gDataCnt; + if (csSave->gammaTable) { +#ifdef __BEOS__ + // Windows are gamma-corrected by BeOS + const bool can_do_gamma = (display_type == DIS_SCREEN); +#else + const bool can_do_gamma = true; +#endif + if (can_do_gamma) { + uint32 gamma_table = csSave->gammaTable; + red_gamma = Mac2HostAddr(gamma_table + gFormulaData + ReadMacInt16(gamma_table + gFormulaSize)); + int chan_cnt = ReadMacInt16(gamma_table + gChanCnt); + if (chan_cnt == 1) + green_gamma = blue_gamma = red_gamma; + else { + int ofs = ReadMacInt16(gamma_table + gDataCnt); + green_gamma = red_gamma + ofs; + blue_gamma = green_gamma + ofs; + } + gamma_data_width = ReadMacInt16(gamma_table + gDataWidth); + do_gamma = true; } } // Set palette rgb_color *d_pal; - if (start == -1) { // Indexed + if (start == 0xffff) { // Indexed for (int i=0; i<=count; i++) { - d_pal = &(mac_pal[(*s_pal).value]); - uint8 red = (*s_pal).red >> 8; - uint8 green = (*s_pal).green >> 8; - uint8 blue = (*s_pal).blue >> 8; + d_pal = mac_pal + (ReadMacInt16(s_pal + csValue) & 0xff); + uint8 red = (uint16)ReadMacInt16(s_pal + csRed) >> 8; + uint8 green = (uint16)ReadMacInt16(s_pal + csGreen) >> 8; + uint8 blue = (uint16)ReadMacInt16(s_pal + csBlue) >> 8; if (csSave->luminanceMapping) red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16; if (do_gamma) { @@ -329,14 +325,14 @@ static int16 VideoControl(uint32 pb, Vid (*d_pal).red = red; (*d_pal).green = green; (*d_pal).blue = blue; - s_pal++; + s_pal += 8; } - } else { // Sequential - d_pal = &(mac_pal[start]); + } else { // Sequential + d_pal = mac_pal + start; for (int i=0; i<=count; i++) { - uint8 red = (*s_pal).red >> 8; - uint8 green = (*s_pal).green >> 8; - uint8 blue = (*s_pal).blue >> 8; + uint8 red = (uint16)ReadMacInt16(s_pal + csRed) >> 8; + uint8 green = (uint16)ReadMacInt16(s_pal + csGreen) >> 8; + uint8 blue = (uint16)ReadMacInt16(s_pal + csBlue) >> 8; if (csSave->luminanceMapping) red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16; if (do_gamma) { @@ -347,51 +343,44 @@ static int16 VideoControl(uint32 pb, Vid (*d_pal).red = red; (*d_pal).green = green; (*d_pal).blue = blue; - d_pal++; s_pal++; + d_pal++; + s_pal += 8; } } video_set_palette(); return noErr; } - case cscSetGamma: // SetGamma - D(bug("SetGamma\n")); - return set_gamma(csSave, ReadMacInt32(param)); + case cscSetGamma: { // SetGamma + uint32 user_table = ReadMacInt32(param + csGTable); + D(bug("SetGamma %08x\n", user_table)); + return set_gamma(csSave, ReadMacInt32(user_table)); + } case cscGrayPage: { // GrayPage - D(bug("GrayPage\n")); - uint32 *screen = (uint32 *)csSave->saveBaseAddr; - uint32 pattern; - uint32 row_bytes = VModes[cur_mode].viRowBytes; - switch (VModes[cur_mode].viAppleMode) { - case APPLE_8_BIT: - pattern=0xff00ff00; - for (int i=0;i>2);j++) - screen[j] = pattern; - pattern = ~pattern; - screen = (uint32 *)((uint32)screen + row_bytes); - } - break; - case APPLE_16_BIT: - pattern=0xffff0000; - for (int i=0;i>1);j++) - screen[j]=pattern; - pattern = ~pattern; - screen = (uint32 *)((uint32)screen + row_bytes); - } - break; - case APPLE_32_BIT: - pattern=0xffffffff; - for (int i=0;isaveBaseAddr; + uint32 pat = pattern[VModes[cur_mode].viAppleMode - APPLE_1_BIT]; + bool invert = (VModes[cur_mode].viAppleMode == APPLE_32_BIT); + for (uint32 y=0; yviType != DIS_INVALID) { + if (p->viAppleID == id) { + x = p->viXsize; + y = p->viYsize; + return; + } + p++; + } + x = y = 0; +} + static int16 VideoStatus(uint32 pb, VidLocals *csSave) { int16 code = ReadMacInt16(pb + csCode); @@ -547,30 +551,40 @@ static int16 VideoStatus(uint32 pb, VidL case cscGetEntries: { // GetEntries D(bug("GetEntries\n")); - ColorSpec *d_pal = (ColorSpec *)Mac2HostAddr(ReadMacInt32(param + csTable)); - int16 start = ReadMacInt16(param + csStart); - int16 count = ReadMacInt16(param + csCount); + uint32 d_pal = ReadMacInt32(param + csTable); + uint16 start = ReadMacInt16(param + csStart); + uint16 count = ReadMacInt16(param + csCount); rgb_color *s_pal; if ((VModes[cur_mode].viAppleMode == APPLE_32_BIT)|| (VModes[cur_mode].viAppleMode == APPLE_16_BIT)) { D(bug("ERROR: GetEntries in direct mode \n")); return statusErr; } - if (start >= 0) { // indexed get - s_pal = &(mac_pal[start]); + + if (start == 0xffff) { // Indexed for (uint16 i=0;i 255) + return paramErr; + s_pal = mac_pal + start; for (uint16 i=0;igammaTable; + if (private_data != NULL) { // Might be left over from a reboot + if (private_data->gammaTable) + Mac_sysfree(private_data->gammaTable); + if (private_data->regEntryID) + Mac_sysfree(private_data->regEntryID); + } delete private_data; - iocic_tvect = (uint32)FindLibSymbol("\021DriverServicesLib", "\023IOCommandIsComplete"); + iocic_tvect = FindLibSymbol("\021DriverServicesLib", "\023IOCommandIsComplete"); D(bug("IOCommandIsComplete TVECT at %08lx\n", iocic_tvect)); if (iocic_tvect == 0) { printf("FATAL: VideoDoDriverIO(): Can't find IOCommandIsComplete()\n"); err = -1; break; } - vslnewis_tvect = (uint32)FindLibSymbol("\020VideoServicesLib", "\026VSLNewInterruptService"); + vslnewis_tvect = FindLibSymbol("\020VideoServicesLib", "\026VSLNewInterruptService"); D(bug("VSLNewInterruptService TVECT at %08lx\n", vslnewis_tvect)); if (vslnewis_tvect == 0) { printf("FATAL: VideoDoDriverIO(): Can't find VSLNewInterruptService()\n"); err = -1; break; } - vsldisposeis_tvect = (uint32)FindLibSymbol("\020VideoServicesLib", "\032VSLDisposeInterruptService"); + vsldisposeis_tvect = FindLibSymbol("\020VideoServicesLib", "\032VSLDisposeInterruptService"); D(bug("VSLDisposeInterruptService TVECT at %08lx\n", vsldisposeis_tvect)); if (vsldisposeis_tvect == 0) { printf("FATAL: VideoDoDriverIO(): Can't find VSLDisposeInterruptService()\n"); err = -1; break; } - vsldois_tvect = (uint32)FindLibSymbol("\020VideoServicesLib", "\025VSLDoInterruptService"); + vsldois_tvect = FindLibSymbol("\020VideoServicesLib", "\025VSLDoInterruptService"); D(bug("VSLDoInterruptService TVECT at %08lx\n", vsldois_tvect)); if (vsldois_tvect == 0) { printf("FATAL: VideoDoDriverIO(): Can't find VSLDoInterruptService()\n"); err = -1; break; } - nqdmisc_tvect = (uint32)FindLibSymbol("\014InterfaceLib", "\007NQDMisc"); + nqdmisc_tvect = FindLibSymbol("\014InterfaceLib", "\007NQDMisc"); D(bug("NQDMisc TVECT at %08lx\n", nqdmisc_tvect)); if (nqdmisc_tvect == 0) { printf("FATAL: VideoDoDriverIO(): Can't find NQDMisc()\n"); @@ -916,33 +950,43 @@ int16 VideoDoDriverIO(void *spaceID, voi } private_data = new VidLocals; - private_data->gammaTable = NULL; - memcpy(private_data->regEntryID, (uint8 *)commandContents + 2, 16); // DriverInitInfo.deviceEntry + private_data->gammaTable = 0; + private_data->regEntryID = Mac_sysalloc(sizeof(RegEntryID)); + if (private_data->regEntryID == 0) { + printf("FATAL: VideoDoDriverIO(): Can't allocate service owner\n"); + err = -1; + break; + } + Mac2Mac_memcpy(private_data->regEntryID, commandContents + 2, 16); // DriverInitInfo.deviceEntry private_data->interruptsEnabled = false; // Disable interrupts break; case kFinalizeCommand: case kSupersededCommand: - if (private_data != NULL) - delete private_data->gammaTable; + if (private_data != NULL) { + if (private_data->gammaTable) + Mac_sysfree(private_data->gammaTable); + if (private_data->regEntryID) + Mac_sysfree(private_data->regEntryID); + } delete private_data; private_data = NULL; break; case kOpenCommand: - err = VideoOpen((uint32)commandContents, private_data); + err = VideoOpen(commandContents, private_data); break; case kCloseCommand: - err = VideoClose((uint32)commandContents, private_data); + err = VideoClose(commandContents, private_data); break; case kControlCommand: - err = VideoControl((uint32)commandContents, private_data); + err = VideoControl(commandContents, private_data); break; case kStatusCommand: - err = VideoStatus((uint32)commandContents, private_data); + err = VideoStatus(commandContents, private_data); break; case kReadCommand: