From 1461b362da297cf9b395a7b55c320e2f4c6a7024 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 7 Jul 2015 12:13:13 -0400 Subject: [PATCH] screen_savers: Import Nebula. This is an unmodified version of Axel's "Nebula" screensaver, except with the RSRC converted to an RDEF. --- src/add-ons/screen_savers/nebula/Nebula.cpp | 793 ++++++++++++++++++ src/add-ons/screen_savers/nebula/Nebula.rdef | 65 ++ src/add-ons/screen_savers/nebula/draw.S | 136 +++ src/add-ons/screen_savers/nebula/draw_stars.S | 78 ++ src/add-ons/screen_savers/nebula/makefile | 48 ++ 5 files changed, 1120 insertions(+) create mode 100644 src/add-ons/screen_savers/nebula/Nebula.cpp create mode 100644 src/add-ons/screen_savers/nebula/Nebula.rdef create mode 100644 src/add-ons/screen_savers/nebula/draw.S create mode 100644 src/add-ons/screen_savers/nebula/draw_stars.S create mode 100644 src/add-ons/screen_savers/nebula/makefile diff --git a/src/add-ons/screen_savers/nebula/Nebula.cpp b/src/add-ons/screen_savers/nebula/Nebula.cpp new file mode 100644 index 0000000000..a77c12ce02 --- /dev/null +++ b/src/add-ons/screen_savers/nebula/Nebula.cpp @@ -0,0 +1,793 @@ +/* Nebula - a screen saver for the BeOS +** +** Copyright (c) 2001-2004 pinc Software. All Rights Reserved. +** Effect from corTeX / Optimum +*/ + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define VERSION_STRING "1.2.0 (August 21st 2004)" + +typedef struct +{ + int x,y,z,r; +} p3; + +typedef float matrix[3][3]; + +#define GMAX 5000 +p3 gal[GMAX]; +float precos[512]; +float presin[512]; + +typedef unsigned short word; + +extern "C" { + void memshset(char *dst, int center_shade,int fixed_shade, int length_2); + void mblur(char *src, int nbpixels); + + void draw_stars320(char *, char); + void draw_stars512(char *, char); + void draw_stars576(char *, char); + void draw_stars640(char *, char); + void draw_stars800(char *, char); + void draw_stars1024(char *, char); + void draw_stars1152(char *, char); + void draw_stars1280(char *, char); + void draw_stars1400(char *, char); + void draw_stars1600(char *, char); +} + +const uint32 kMsgWidth = 'widt'; +const uint32 kMsgColorScheme = 'cols'; +const uint32 kMsgBlankBorders = 'blbr'; +const uint32 kMsgMotionBlur = 'blur'; +const uint32 kMsgSpeed = 'sped'; +const uint32 kMsgFrames = 'mfps'; + +void (*gDrawStarFunc)(char *,char); +float gSpeed; +bool gMotionBlur; +int32 gSettingsWidth; +int32 gWidth; +int32 gHeight; +float gMaxFramesPerSecond; +BBitmap *gBitmap; +BScreenSaver *gScreenSaver; +uint32 gPalette[256]; +int8 gPaletteScheme,gBlankBorders; +char *gBuffer8; /* working 8bit buffer */ + + +inline float +ocos(float a) +{ + return (precos[(int)(a*256/M_PI) & 511]); +} + +inline float +osin(float a) +{ + return (presin[(int)(a*256/M_PI) & 511]); +} + + +void +mulmat(matrix *a, matrix *b, matrix *c) +{ + int i,j; + + for (i = 0;i < 3;i++) { + for (j = 0;j < 3;j++) { + (*c)[i][j] = (*a)[i][0] * (*b)[0][j] + + (*a)[i][1] * (*b)[1][j] + + (*a)[i][2] * (*b)[2][j]; + } + } +} + + +inline void +mulvec(matrix *a, float *x, float *y, float *z) +{ + float nx = *x,ny = *y,nz = *z; + + *x = nx*(*a)[0][0] + ny*(*a)[0][1] + nz*(*a)[0][2]; + *y = nx*(*a)[1][0] + ny*(*a)[1][1] + nz*(*a)[1][2]; + *z = nx*(*a)[2][0] + ny*(*a)[2][1] + nz*(*a)[2][2]; +} + + +void +setrmat(float a, float b, float c, matrix *m) +{ + int i,j; + for (i = 0;i < 3;i++) + for (j = 0;j < 3;j++) + (*m)[i][j] = (float)(i == j); + + if (a != 0) { + (*m)[0][0] = cos(a); (*m)[0][1] = sin(a); + (*m)[1][0] = sin(a); (*m)[1][1] = -cos(a); + return; + } + if (b != 0) { + (*m)[0][0] = cos(b); (*m)[0][2] = sin(b); + (*m)[2][0] = sin(b); (*m)[2][2] = -cos(b); + return; + } + (*m)[1][1] = cos(c); (*m)[1][2] = sin(c); + (*m)[2][1] = sin(c); (*m)[2][2] = -cos(c); +} + + +void +rotate3d(float *xr, float *yr, float *zr, /* point to rotate */ + float ax, float ay, float az) /* the 3 angles (order ?..) */ +{ + float xr2, yr2, zr2; + + xr2 = (*xr*ocos(az) + *yr*osin(az)); + yr2 = (*xr*osin(az) - *yr*ocos(az)); + *xr = xr2; + *yr = yr2; + + xr2 = (*xr*ocos(ay) + *zr*osin(ay)); + zr2 = (*xr*osin(ay) - *zr*ocos(ay)); + *xr = xr2; + *zr = zr2; + + zr2 = (*zr*ocos(ax) + *yr*osin(ax)); + yr2 = (*zr*osin(ax) - *yr*ocos(ax)); + *zr = zr2; + *yr = yr2; +} + + +void +drawshdisk(int x0, int y0, int r) +{ + int x = 0; + int y; + int ly; /* last y */ + int delta; + int c; /* color at center */ + int d; /* delta */ + +#define SLIMIT 17 +#define SRANGE 15 + + if (r <= SLIMIT) { + /* range checking is already (more or less) done... */ + (*gDrawStarFunc)(&gBuffer8[x0 + gWidth*y0], 10+r*5); + //gBuffer8[x0+W*y0] = 10+r*5; + return; + } + + if (r < SLIMIT+SRANGE) + r = ((r-SLIMIT)*SLIMIT)/SRANGE+1; + + y = ly = r; /* AAaargh */ + delta = 3-2*r; + + do { + if (y != ly) { + /* dont overlap these lines */ + c = ((r-y+1)<<13)/r; + d = -c/(x+1); + + if (y == x+1) /* this would overlap with the next x lines */ + goto TOTO; /* WHY NOT */ + + /* note : for "normal" numbers (not too big) : + (unsigned int)(x) < M <=> 0<=xH ) + + This is clearly a stupid, unmaintanable, unreadable "optimization". + But i like it :) + */ + if ((uint32)(y0-y-1) < gHeight-3) + memshset(&gBuffer8[x0 + gWidth*(y0-y+1)] ,c,d, x); + if ((uint32)(y0+y-1) < gHeight-3) + memshset(&gBuffer8[x0 + gWidth*(y0+y)] ,c,d, x); + } + TOTO: + c = ((r-x+1)<<13)/r; + d = -c/(y); + + if ((uint32)(y0-x-1) < gHeight-3) + memshset(&gBuffer8[x0 + gWidth*(y0-x)] ,c,d, y); + if ((uint32)(y0+x-1) < gHeight-3) + memshset(&gBuffer8[x0 + gWidth*(y0+x+1)] ,c,d, y); + + ly = y; + if (delta < 0) + delta += 4*x+6; + else { + delta += 4*(x-y)+10; + y--; + } + x++; + } while (x < y); +} + + +void +drawGalaxy() +{ + int r; + int x,y; + float rx,ry,rz; + int i; + float oa,ob,oc; + float t; + float a, b, c; + matrix ma,mb,mc,mr; + + /* t is the parametric coordinate for the animation; + change the scale value to change the speed of anim + (independant of processor speed) + */ + static bigtime_t firstTime = system_time(); + t = ((double)gSpeed * system_time()-firstTime)/1000000.0; //opti_scale_time(0.418, &demo_elapsed_time); + + a = 0.9*t; + b = t; + c = 1.1*t; + + setrmat(a,0,0,&ma); + setrmat(0,b,0,&mb); + mulmat(&ma,&mb,&mc); + setrmat(0,0,c,&ma); + mulmat(&ma,&mc,&mr); + + oa = 140 * osin(a); + ob = 140 * ocos(b); + oc = 240 * osin(c); + + if (gMotionBlur) { + /* mblur does something like that: + * (or did, perhaps it's another version!..) + + for (i=0; i>3) + (gBuffer8[i]>>1); + */ + mblur (gBuffer8, gWidth*gHeight); + } else + memset(gBuffer8,0,gWidth*gHeight); + + for (i = 0; i < GMAX; i++) { + rx = gal[i].x; + ry = gal[i].y; + rz = gal[i].z; + + mulvec(&mr, &rx, &ry, &rz); + + rx += oa; + ry += ob; + rz += oc; + rz += 300; + + if (rz > 5) { + x = (int)(15*rx/(rz/5+1)) + gWidth/2; /* tain jcomprend plus rien */ + y = (int)(15*ry/(rz/5+1)) + gHeight/2; /* a ces formules de daube !! */ + r = (int)(3*gal[i].r / (rz/4+3))+2; + + if (x > 5 && x < gWidth-6 && y > 5 && y < gHeight-6) +// if ((uint32)x < gWidth-1 && (uint32)y < gHeight-1) + drawshdisk(x,y,r); + } + } +} + + +void +setPalette() +{ + int i; + + switch (gPaletteScheme) { + case 0: // yellow + default: + for (i = 0; i < 30; i++) + gPalette[i] = (uint8)(i*8/10) << 16 | (uint8)(i*6/10) << 8; // | (uint8)(i*3/10); + + for (i = 30; i < 256; i++) { + uint8 r = (i); + uint8 g = (i*i >> 8); //(i*8/10); + uint8 b = i >= 240 ? (i-240) << 3 : 0; //(i*2/10); + + gPalette[i] = ((r << 16) | (g << 8) | (b)); + } + break; + case 1: // blue + for (i = 0; i < 30; i++) + gPalette[i] = (uint8)(i*8/10); // << 16 | (uint8)(i*6/10) << 8; // | (uint8)(i*3/10); + + for (i = 30; i < 256; i++) { + uint8 b = (i); + uint8 g = (i*i >> 8); //(i*8/10); + uint8 r = i >= 240 ? (i-240) << 3 : 0; //(i*2/10); + + gPalette[i] = ((r << 16) | (g << 8) | (b)); + } + break; + case 2: // red + for (i = 0;i < 128;i++) + gPalette[i] = (uint8)i << 16; // << 16 | (uint8)(i*6/10) << 8; // | (uint8)(i*3/10); + + for (i = 128;i < 256;i++) + { + uint8 r = i; + uint8 c = (uint8)((cos((i-256) / 42.0)*0.5 + 0.5)*225); + + gPalette[i] = ((r << 16) | (c << 8) | c); + } +/* for (i = 192;i < 224;i++) + { + uint8 c = (i-192); + gPalette[i] = gPalette[i] & 0xff0000 | c << 8 | c; + } + for (i = 224;i < 256;i++) + { + uint8 c = (i-224)/2; + c = 32 + c*c*6/10; + gPalette[i] = gPalette[i] & 0xff0000 | c << 8 | c; + } +*/ break; + case 3: // green + for (i = 0; i < 30; i++) + gPalette[i] = (uint8)(i*8/10) << 8; // << 16 | (uint8)(i*6/10) << 8; // | (uint8)(i*3/10); + + for (i = 30; i < 256; i++) { + uint8 g = (i); + uint8 r = (i*i >> 8); //(i*8/10); + uint8 b = i >= 240 ? (i-240) << 3 : 0; //(i*2/10); + + gPalette[i] = ((r << 16) | (g << 8) | (b)); + } + break; + case 4: // grey + for (i = 0; i < 256; i++) { + uint8 c = i*15/16 + 10; + gPalette[i] = c << 16 | c << 8 | c; + } + break; + case 5: // cold + for (i = 0; i < 30; i++) + gPalette[i] = (uint8)(i*8/10) << 16; // << 16 | (uint8)(i*6/10) << 8; // | (uint8)(i*3/10); + + for (i = 30; i < 256; i++) { + uint8 r = i; + uint8 c = (uint8)((cos((i-255) / 82.0)*0.5 + 0.5)*255); + + gPalette[i] = ((r << 16) | (c << 8) | c); + } + break; + case 6: // original + for (i = 0; i < 256; i++) { + uint32 c = *(char *)&i; + gPalette[i] = c << 16 | c << 8; + } + break; + } +/* for (i = 0;i < 256;i++) + { + uint8 r = (i); + uint8 g = (i*i >> 8); //(i*8/10); + uint8 b = 0; //(i*2/10); + + gPalette[i] = ((r << 16) | (g << 8) | (b)); + } +*/ +/* for (i = 240;i < 256;i++) + gPalette[i] = (uint8)i << 16 | (uint8)i << 8 | (uint8)(i*6/10); +*/ +} + + +/***********************************************************************************/ +// #pragma mark - +// #pragma mark SimpleSlider + +class SimpleSlider : public BSlider { + public: + SimpleSlider(BRect frame, const char *label, BMessage *msg) + : BSlider(frame, B_EMPTY_STRING, B_EMPTY_STRING, msg, 1, 100) + { + SetLimitLabels("1", "100"); + SetHashMarks(B_HASH_MARKS_BOTTOM); + SetHashMarkCount(11); + fLabel = label; + }; + + char *UpdateText() const + { + sprintf(fText, "%s: %d", fLabel, Value()); + + return fText; + }; + + private: + mutable char fText[32]; + const char *fLabel; +}; + + +/***********************************************************************************/ +// #pragma mark - + + +class SettingsView : public BView { + public: + SettingsView(BRect frame); + + virtual void AttachedToWindow(); + virtual void MessageReceived(BMessage *msg); + + private: + BMenuField *fWidthMenu,*fColorMenu,*fBorderMenu; + BCheckBox *fMotionCheck; + BSlider *fSpeedSlider,*fFramesSlider; +}; + + +SettingsView::SettingsView(BRect frame) + : BView(frame,"",B_FOLLOW_NONE,B_WILL_DRAW) +{ + MoveBy(0, -25); // the view is not where it should +} + + +void +SettingsView::AttachedToWindow() +{ + int32 height,y; + { + font_height fontHeight; + GetFontHeight(&fontHeight); + height = (int32)(fontHeight.ascent + fontHeight.descent + fontHeight.leading)+10; + } + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + BRect rect(10,0,0,25); + rect.right = Bounds().right; + + BStringView *string = new BStringView(rect,B_EMPTY_STRING,"Nebula"); + string->SetFontSize(18.0); + AddChild(string); + + rect.left += 60; rect.bottom -= 2; + string = new BStringView(rect,B_EMPTY_STRING,VERSION_STRING); + AddChild(string); + +// rect.OffsetBy(0,height+5); + rect.left = 10; rect.top = 27; rect.bottom = 17+height; + string = new BStringView(rect,B_EMPTY_STRING,"© 2001-2004 pinc Software, Axel Dörfler."); + string->SetAlignment(B_ALIGN_CENTER); + AddChild(string); + + BPopUpMenu *popMenu = new BPopUpMenu(""); + BMenuItem *item; + + int32 widths[] = { 320, 512, 576, 640, 800, 1024, 1152, 1280, 1400, 1600 }; + for (int32 i = 0; i < sizeof(widths) / sizeof(widths[0]); i++) { + BMessage *msg = new BMessage(kMsgWidth); + char label[64]; + sprintf(label, "%ld pixel", widths[i]); + msg->AddInt32("width", widths[i]); + popMenu->AddItem(item = new BMenuItem(label, msg)); + + if (gSettingsWidth == widths[i]) + item->SetMarked(true); + } + + popMenu->SetTargetForItems(this); + rect.left = 10; rect.OffsetBy(0,height); + fWidthMenu = new BMenuField(rect, "res", "Internal Horizontal Resolution:", popMenu); + fWidthMenu->SetDivider(155); + AddChild(fWidthMenu); + + popMenu = new BPopUpMenu(""); + + const char *colorSchemes[] = {"yellow","blue/cyan","red","green","grey","cold","orange (original)"}; + for (int i = 0; i < 7; i++) { + BMessage *msg = new BMessage(kMsgColorScheme); + msg->AddInt8("scheme",(int8)i); + popMenu->AddItem(item = new BMenuItem(colorSchemes[i],msg)); + if (gPaletteScheme == i) + item->SetMarked(true); + } + + popMenu->SetTargetForItems(this); + rect.OffsetBy(0,height); + fColorMenu = new BMenuField(rect,"col","Color Scheme:",popMenu); + fColorMenu->SetDivider(110); + AddChild(fColorMenu); + + popMenu = new BPopUpMenu(""); + + const char *blankBorderFormats[] = {"fullscreen, no borders","16:9, wide-screen","2:3.5, cinemascope","only a slit"}; + for (int8 i = 0;i < 4;i++) + { + BMessage *msg = new BMessage(kMsgBlankBorders); + msg->AddInt8("border",i); + popMenu->AddItem(item = new BMenuItem(blankBorderFormats[i],msg)); + if (gBlankBorders == i) + item->SetMarked(true); + } + + popMenu->SetTargetForItems(this); + rect.OffsetBy(0,height); + fBorderMenu = new BMenuField(rect,"cinema","Blank Border Format:",popMenu); + fBorderMenu->SetDivider(110); + AddChild(fBorderMenu); + + rect.OffsetBy(0,height+3); + fMotionCheck = new BCheckBox(rect,B_EMPTY_STRING,"Enable Motion Blur",new BMessage(kMsgMotionBlur)); + fMotionCheck->SetTarget(this); + fMotionCheck->SetValue((int)gMotionBlur); + AddChild(fMotionCheck); + fMotionCheck->ResizeToPreferred(); + + rect.OffsetBy(0, height - 3); rect.bottom += 2*height; rect.right -= 10; + fSpeedSlider = new SimpleSlider(rect,"Speed",new BMessage(kMsgSpeed)); + fSpeedSlider->SetValue((gSpeed - 0.002)/0.05); + fSpeedSlider->SetTarget(this); + AddChild(fSpeedSlider); + fSpeedSlider->ResizeToPreferred(); + + rect.OffsetBy(0, 2 * height + 15); + fFramesSlider = new SimpleSlider(rect,"Maximum Frames Per Second",new BMessage(kMsgFrames)); + fFramesSlider->SetValue(gMaxFramesPerSecond); + fFramesSlider->SetTarget(this); + AddChild(fFramesSlider); + fFramesSlider->ResizeToPreferred(); +} + + +void +SettingsView::MessageReceived(BMessage *msg) +{ + switch(msg->what) { + case kMsgWidth: + if (msg->FindInt32("width",&gSettingsWidth) == B_OK) { + if (gSettingsWidth > 1600) + gSettingsWidth = 1600; + else if (gSettingsWidth < 320) + gSettingsWidth = 320; + } + break; + case kMsgColorScheme: + if (msg->FindInt8("scheme",&gPaletteScheme) == B_OK) + setPalette(); + break; + case kMsgBlankBorders: + msg->FindInt8("border",&gBlankBorders); + break; + case kMsgMotionBlur: + gMotionBlur = fMotionCheck->Value() > 0; + break; + case kMsgSpeed: + gSpeed = 0.002 + 0.05 * fSpeedSlider->Value(); + //printf("value = %d, gSpeed = %f\n",fSpeedSlider->Value(),gSpeed); + break; + case kMsgFrames: + gMaxFramesPerSecond = fFramesSlider->Value(); + gScreenSaver->SetTickSize((bigtime_t)(1000000LL / gMaxFramesPerSecond)); + break; + } +} + + + +/***********************************************************************************/ +// #pragma mark - + + +class Nebula : public BScreenSaver { + public: + Nebula(BMessage *message, image_id id); + + virtual void StartConfig(BView *view); + virtual status_t SaveState(BMessage *state) const; + + virtual status_t StartSaver(BView *view, bool preview); + virtual void StopSaver(); + virtual void Draw(BView *view, int32 frame); + + private: + float fFactor; + bool fStarted; +}; + + +Nebula::Nebula(BMessage *message, image_id id) + : BScreenSaver(message, id) +{ + message->FindFloat("speed", 0, &gSpeed); + message->FindInt32("width", 0, &gSettingsWidth); + message->FindBool("motionblur", 0, &gMotionBlur); + message->FindFloat("max_fps", 0, &gMaxFramesPerSecond); + message->FindInt8("scheme", 0, &gPaletteScheme); + message->FindInt8("border", 0, &gBlankBorders); + + if (gSpeed < 0.01f) + gSpeed = 0.4f; + if (gSettingsWidth < 320) + gSettingsWidth = 320; + if (gMaxFramesPerSecond < 1.f) + gMaxFramesPerSecond = 40.0f; + + gScreenSaver = this; +} + + +void +Nebula::StartConfig(BView *view) +{ + view->AddChild(new SettingsView(view->Frame())); +} + + +status_t +Nebula::SaveState(BMessage *state) const +{ + state->AddFloat("speed", gSpeed); + state->AddInt32("width", gSettingsWidth); + state->AddBool("motionblur", gMotionBlur); + state->AddFloat("max_fps", gMaxFramesPerSecond); + state->AddInt8("scheme", gPaletteScheme); + state->AddInt8("border", gBlankBorders); + + return B_OK; +} + + +status_t +Nebula::StartSaver(BView *view, bool preview) +{ + // initialize palette + setPalette(); + + int i; + for (i = 0; i < 512; i++) { + precos[i]=cos(i*M_PI/256); + presin[i]=sin(i*M_PI/256); + } + + // uniforme cubique +/* for (i = 0;i < GMAX;i++) + { + gal[i].x = 1*((rand()&1023) - 512); + gal[i].y = 1*((rand()&1023) - 512); + gal[i].z = 1*((rand()&1023) - 512); + gal[i].r = rand()&63; + } +*/ + + for (i = 0; i < GMAX; i++) { + float r, th, h, dth; + + r = rand()*1.0 / RAND_MAX; + r = (1-r)*(1-r)+0.05; + + if (r < 0.12) + th = rand()*M_PI*2/RAND_MAX; + else { + th = (rand()&3)*M_PI_2 + r*r*2; + dth = rand()*1.0/RAND_MAX; + dth = dth*dth*2; + th+=dth; + } + gal[i].x = (int)(512*r*cos(th)); + gal[i].z = (int)(512*r*sin(th)); + h = (1+cos(r*M_PI))*150; + dth = rand()*1.0/RAND_MAX; + gal[i].y = (int)(h*(dth-0.5)); + gal[i].r = (int)((2-r)*60 + 31); + } + gal[0].x = gal[0].y = gal[0].z = 0; + gal[0].r = 320; + + if (preview) + gWidth = 320; + else + gWidth = gSettingsWidth; + + fFactor = (view->Bounds().Width()+1) / gWidth; + if ((int)fFactor != fFactor) + fFactor += 0.01; + + // 4:3 + gHeight = (int32)((view->Bounds().Height()+1)/fFactor + 0.5f); + // calculate blank border format (if not in preview) + if (!preview) switch (gBlankBorders) { + case 1: // 16:9 + gHeight = (int32)(gHeight * 0.703125 + 0.5); + break; + case 2: // 2:3.5 + gHeight = (int32)(gHeight * 0.534 + 0.5); + break; + case 3: + gHeight /= 5; + break; + } + view->SetScale(fFactor); + + switch (gWidth) { + default: + case 320: gDrawStarFunc = draw_stars320; break; + case 512: gDrawStarFunc = draw_stars512; break; + case 576: gDrawStarFunc = draw_stars576; break; + case 640: gDrawStarFunc = draw_stars640; break; + case 800: gDrawStarFunc = draw_stars800; break; + case 1024: gDrawStarFunc = draw_stars1024; break; + case 1152: gDrawStarFunc = draw_stars1152; break; + case 1280: gDrawStarFunc = draw_stars1280; break; + case 1400: gDrawStarFunc = draw_stars1400; break; + case 1600: gDrawStarFunc = draw_stars1600; break; + } + + gBitmap = new BBitmap(BRect(0, 0, gWidth - 1, gHeight - 1), B_RGB32); + gBuffer8 = (char *)malloc(gWidth * gHeight); + + SetTickSize((bigtime_t)(1000000LL / gMaxFramesPerSecond)); + fStarted = true; + + return B_OK; +} + + +void +Nebula::StopSaver() +{ + free(gBuffer8); + gBuffer8 = NULL; + + delete gBitmap; + gBitmap = NULL; +} + + +void +Nebula::Draw(BView *view, int32) +{ + if (fStarted) { + view->SetHighColor(0, 0, 0, 0); + view->FillRect(view->Frame()); + view->MovePenTo(0, (view->Bounds().Height() / fFactor - 1 - gHeight) / 2); + + fStarted = false; + } + uint32 *buffer32 = (uint32 *)gBitmap->Bits(); + + drawGalaxy(); + + for (int x = 0, end = gWidth * gHeight; x < end; x++) + buffer32[x] = gPalette[(uint8)gBuffer8[x]]; + + view->DrawBitmap(gBitmap); +} + + +/***********************************************************************************/ +// #pragma mark - + + +extern "C" _EXPORT BScreenSaver * +instantiate_screen_saver(BMessage *message, image_id image) +{ + return new Nebula(message, image); +} diff --git a/src/add-ons/screen_savers/nebula/Nebula.rdef b/src/add-ons/screen_savers/nebula/Nebula.rdef new file mode 100644 index 0000000000..6f2a8ac4b4 --- /dev/null +++ b/src/add-ons/screen_savers/nebula/Nebula.rdef @@ -0,0 +1,65 @@ +resource app_version { + major = 1, + middle = 2, + minor = 0, + + variety = B_APPV_FINAL, + internal = 0, + + short_info = "Nebula2", + long_info = "Copyright ©2001-2004 pinc Software." +}; + +resource large_icon array { + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF" + $"FFFFFFFFFFFFFF00000000000000000000FFFFFFFFFFFFFFFF00FFFFFFFFFFFF" + $"FFFFFFFF0000001B3F3F3F3F3F3F3F3F3F0000FFFFFFFFFF00FFFF000000FFFF" + $"FFFFFF001B3F1B3F3F1B3F1C1B161919193F3F0000FFFF000000FFFFFF00FFFF" + $"FFFF003F3F1B1C1B3F3F3F3F1C1B1C161619193F1C0000FFFFFFFFFF00FFFFFF" + $"FFFF003F153F3F1B3F1B1C1C3F3F1C161616161919193F00FFFFFF000000FFFF" + $"FFFF003F3F3F3F3F3F1B1C3F1C1C3F3F1C1B1C161619193F00FFFFFFFFFFFFFF" + $"FFFF003F3F3F3F3F3F3F3F3F1C1B1C1C3F3F3F1B1C16163F3F00FFFFFFFFFFFF" + $"FF003F3F3F3F153F3F3F3F3F3F1B1C3F1C1C3F3F3F16163F3F3F00FFFFFFFFFF" + $"FF003F3F3F3F1515153F3F3F3F3F3F3F1C3F1C1C1B1C3F3F3F3F3F00FFFFFFFF" + $"FF003F3F3F1517171715153F3F3F3F3F3F3F3F3F1C1C3F1C3F3F3F00FFFFFFFF" + $"FF003F3F3F15171717171715153F3F3F3F3F3F3F3F3F1C3F3F3F3F3F00FFFFFF" + $"FF003F3F3F1517173F3F17171715153F3F3F3F3F3F3F3F3F3F0E3F3F00FFFFFF" + $"003F3F3F3F15173F3F3F3F3F3F171715153F3F3F3F3F3F3F0E0F3F3F00FFFFFF" + $"003F3F3F3F17173F3F3F3F3F3F3F3F171715153F3F3F3F3F0F0E3F3F00FFFFFF" + $"003F0000000000003F3F3F3F3F3F3F3F1717173F3F3F113F3F0F0E3F3F00FFFF" + $"000000150A0A1C000000003F3F3F3F3F3F3F3F113F3F113F3F0F0F3F3F00FFFF" + $"FFFF00150A0A1C0000000000003F3F3F3F3F3F113F3F113F3F3F3F3F3F0000FF" + $"FFFF00150A0A1C00000000000000003F3F3F3F113F3F113F3F3F3F00000000FF" + $"FFFF00150A0B1C000000000000000000003F113F3F3F113F3F3F0000FFFFFFFF" + $"FFFF001500001B1B1C000000000000000000123F3F3F113F3F000000FFFFFFFF" + $"FFFF0000151515151B1C1C00000000000000123F3F3F113F3F000F00FFFFFFFF" + $"FFFFFF000015151515151C1C1C000000000000003F3F3F11000F0F001111FFFF" + $"FFFFFFFFFF0000151515151C1C1C1B000000000000003F3F000F0F00111111FF" + $"FFFFFFFFFFFFFF0000151515151B1C1C1B0000001B1500000F0F0F0011111111" + $"FFFFFFFFFFFFFFFFFF0000151515151C1B1C1C001B16150F0F0E0F0011111111" + $"FFFFFFFFFFFFFFFFFFFFFF0000151615151C1B1C1C15150F0F0F0F0011111111" + $"FFFFFFFFFFFFFFFFFFFFFFFFFF0000151615151C1B16150F0F0F0E00111111FF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00001515151615150F0F0F00111111FFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000151515160E0F00111111FFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000016150F00111111FFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000111111FFFFFFFFFF" +}; + +resource mini_icon array { + $"FFFFFFFF0404040404FFFFFF00FFFFFF" + $"FFFF00003F3F3F3F3F00FFFF00FF00FF" + $"FF003F1C3F3F1C1C16190A00FFFF00FF" + $"FF003F3F3F1C1C3F1C1C161900FFFFFF" + $"FF043F153F3F3F1C1C3F3F163F00FFFF" + $"043F3F1717153F3F3F3F1C3F3F0AFFFF" + $"043F3F173F1717153F3F3F3F3F3F00FF" + $"003F3F173F3F17173F153F3F0F3F00FF" + $"00000A0A00000017173F3F113F0F04FF" + $"FF000A1C00000000173F3F113F3F00FF" + $"FF00001C1C00000000123F113F00FFFF" + $"FF000016161C000000003F3F000611FF" + $"FFFFFF000016161C1B000A000F061111" + $"FFFFFFFFFF000016151B1C150F061111" + $"FFFFFFFFFFFFFF06001516150F0011FF" + $"FFFFFFFFFFFFFFFFFF0600060011FFFF" +}; diff --git a/src/add-ons/screen_savers/nebula/draw.S b/src/add-ons/screen_savers/nebula/draw.S new file mode 100644 index 0000000000..d52243855e --- /dev/null +++ b/src/add-ons/screen_savers/nebula/draw.S @@ -0,0 +1,136 @@ + +.text + +/* memshset (char *dst, int center_shade,int fixed_shade, int length_2) */ +/* dst is the *center* of the dst segment */ +/* center shade is the initial color (at center) (!! 8:8 also) */ +/* fixed_shade is the fixed point increment (8:8) */ +/* length_2 is the 1/2 length to set (to the left, and to the right) */ + +/* a memaddshadedset function (or something like that ) */ + +.globl memshset +.type memshset,@function + + +memshset: + pushl %ebp + movl %esp,%ebp + + pushl %edi /* registres a sauvegarder (convention gcc) */ + pushl %esi + pushl %ebx + + movl 8(%ebp),%edi /* dst */ + movl 12(%ebp),%eax + movl 16(%ebp),%ebx /* fixed point */ + movl 20(%ebp),%ecx /* half length */ + + orl %ecx,%ecx + jz 2f + + movl %edi,%esi + subl %ecx,%edi /* %edi left segment */ + addl %ecx,%esi /* %esi right segment */ + incl %esi /* dont overlap at middle */ + + movl %ecx,%edx + negl %edx + decl %edx /* for in-advance incl in loop */ +1: + addl %ebx,%eax /* increment color */ + incl %edx + + addb %ah,(%edi,%ecx) /* increment left pixel */ + jc 3f /* did overflow ? */ + + addb %ah,(%esi,%edx) /* increment right pixel */ + jc 4f + + decl %ecx + jnz 1b + +2: + popl %ebx + popl %esi + popl %edi + + leave + ret +/* function goes on (several exit points): */ +3: + movb $255,(%edi,%ecx) + addb %ah,(%esi,%edx) /* we recopy all the code.. to avoid jmps (hmm some asm guru here : is it really efficient ?.. */ + jc 4f + decl %ecx + jnz 1b + + popl %ebx + popl %esi + popl %edi + + leave + ret + +4: + movb $255,(%esi,%edx) + decl %ecx + jnz 1b + + popl %ebx + popl %esi + popl %edi + + leave + ret +/* function really stops here */ + + +/*********************************** motion blur **********************************/ + +/* do the "motion blur" (actually the pixel fading) */ +.globl mblur +.type mblur,@function + +mblur: + pushl %ebp + movl %esp,%ebp + + pushl %edi + pushl %esi + pushl %ebx + + movl 8(%ebp),%edi /* dst */ + movl 12(%ebp),%ecx /* number */ + movl $0x7f7f7f7f,%edx /* clear 1 upper bits */ + movl $0x1f1f1f1f,%esi /* clear 3 upper bits */ + shrl $2,%ecx + jz 2f + +1: + movl (%edi),%eax + addl $4,%edi + + movl %eax,%ebx + shrl $1,%eax + + + shrl $3,%ebx + andl %edx,%eax + + andl %esi,%ebx + addl %ebx,%eax + + decl %ecx + movl %eax,-4(%edi) + + + jnz 1b + + +2: + popl %ebx + popl %esi + popl %edi + leave + ret diff --git a/src/add-ons/screen_savers/nebula/draw_stars.S b/src/add-ons/screen_savers/nebula/draw_stars.S new file mode 100644 index 0000000000..df27e83889 --- /dev/null +++ b/src/add-ons/screen_savers/nebula/draw_stars.S @@ -0,0 +1,78 @@ + +.text + +/* this function needs a definition from outside (the width of the bitmap) */ + +// #define STAR_WIDTH 320 +// #define STAR_FUNCTION draw_stars320 + +/* draw a star (5 pixels) */ +.globl STAR_FUNCTION +.type STAR_FUNCTION,@function + +STAR_FUNCTION: + pushl %ebp + movl %esp,%ebp + + pushl %edi + + movl 8(%ebp),%edi /* dst */ + movl 12(%ebp),%edx /* inc */ + + addb %dl,(STAR_WIDTH)(%edi) + jnc 3f + movb $255,(STAR_WIDTH)(%edi) + +3: + shrb $1,%dl + movb (%edi),%al + movb (STAR_WIDTH-1)(%edi),%cl + addb %dl,%al + jc 1f + addb %dl,%cl + jc 2f + movb %al,(%edi) + movb %cl,(STAR_WIDTH-1)(%edi) + jmp 31f +1: + addb %dl,%cl + jc 2f + movb $255,(%edi) + movb %cl,(STAR_WIDTH-1)(%edi) + + jmp 31f + +2: + movb $255,(%edi) + movb $255,(STAR_WIDTH-1)(%edi) + + +31: + movb 2*STAR_WIDTH(%edi),%al + movb (STAR_WIDTH+1)(%edi),%cl + addb %dl,%al + jc 11f + addb %dl,%cl + jc 21f + movb %al,2*STAR_WIDTH(%edi) + movb %cl,(STAR_WIDTH+1)(%edi) + popl %edi + leave + ret + + +11: + addb %dl,%cl + jc 21f + movb $255,(2*STAR_WIDTH)(%edi) + movb %cl,(STAR_WIDTH+1)(%edi) + popl %edi + leave + ret + +21: + movb $255,2*STAR_WIDTH(%edi) + movb $255,(STAR_WIDTH+1)(%edi) + popl %edi + leave + ret diff --git a/src/add-ons/screen_savers/nebula/makefile b/src/add-ons/screen_savers/nebula/makefile new file mode 100644 index 0000000000..ebeccb75ca --- /dev/null +++ b/src/add-ons/screen_savers/nebula/makefile @@ -0,0 +1,48 @@ +#include $(TOP)/config/make.cfg + +CFLAGS = -O3 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations +#CFLAGS = -g + +LIBS = -lbe -lscreensaver +NAME = Nebula +FILES = Nebula +ASMFILES = draw +STARFILE = draw_stars +STARWIDTHS = 320 512 576 640 800 1024 1152 1280 1400 1600 +OBJDIR = obj.x86 + +STARFILES := $(foreach f, $(STARWIDTHS), $(STARFILE)$(f)) + +SRCS := $(foreach f, $(FILES), $(f).cpp) +ASMSRCS := $(foreach f, $(ASMFILES), $(f).S) + +OBJS := $(foreach f, $(FILES) $(ASMFILES) $(STARFILES), $(OBJDIR)/$(f).o) + +all: $(NAME) + +install: all + @mv $(NAME) /boot/home/config/add-ons/Screen\ Savers/ + +test: all + @screen_blanker /boot/home/develop/div/ScreenSavers/$(NAME)/$(NAME) + +clean: + @rm $(OBJDIR)/* + +Nebula: $(OBJS) + @echo "Linking $@..." + @$(CC) $(OBJS) -o $@ -nostart $(LIBS) + xres -o $@ $@.rsrc + mimeset -f $@ + +$(OBJDIR)/%.o : %.cpp + $(CC) -c $*.cpp -o $(OBJDIR)/$*.o $(CFLAGS) + +$(OBJDIR)/$(STARFILE)%.o : $(STARFILE).S + $(CC) -c $(STARFILE).S -DSTAR_WIDTH=$* -DSTAR_FUNCTION=draw_stars$* -o $@ + +$(OBJDIR)/%.o : %.S + $(CC) -c $*.S -o $(OBJDIR)/$*.o $(CFLAGS) + +tar zip backup: + @zip `basename $(NAME)`-`date +%Y-%m-%d`.zip *.[chS]* *.rsrc makefile