00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <Assert.h>
00024
00025 #include "SpanBuffer.h"
00026 #include "Ram.h"
00027
00028 #ifdef GENESIS_VERSION_2
00029 #include "errorlog.h"
00030 #else
00031 #define geErrorLog_AddString(Error,xx,yy)
00032 #endif
00033
00034
00035
00036
00037
00038
00039 typedef struct SpanBuffer_Span SpanBuffer_Span;
00040
00041 typedef struct SpanBuffer_Span
00042 {
00043 int Min, Max;
00044 SpanBuffer_Span *Next;
00045 } SpanBuffer_Span;
00046
00047 static SpanBuffer_Span **SpanBuffer_Lines;
00048 static SpanBuffer_Span *SpanBuffer_Spares;
00049 static int SpanBuffer_FirstSpare;
00050 static int SpanBuffer_LineCount;
00051 static int SpanBuffer_MaxSpares;
00052 SpanBuffer_ClipSegment *SpanBuffer_Segments;
00053
00054
00055 void SpanBuffer_Destroy(void)
00056 {
00057 if ( SpanBuffer_Lines != NULL )
00058 geRam_Free(SpanBuffer_Lines);
00059 SpanBuffer_Lines = NULL;
00060
00061 if ( SpanBuffer_Spares != NULL )
00062 geRam_Free(SpanBuffer_Spares);
00063 SpanBuffer_Spares = NULL;
00064
00065 if ( SpanBuffer_Segments != NULL )
00066 geRam_Free(SpanBuffer_Segments);
00067 SpanBuffer_Segments = NULL;
00068 }
00069
00070 void SpanBuffer_Clear(void)
00071 {
00072 int i;
00073 assert(SpanBuffer_Lines!=NULL);
00074
00075 for (i=0; i<SpanBuffer_LineCount; i++)
00076 {
00077 SpanBuffer_Lines[i] = NULL;
00078 }
00079 SpanBuffer_FirstSpare = 0;
00080 }
00081
00082 geBoolean SpanBuffer_Create(int Width, int Height, int MaxSpans)
00083 {
00084 assert( Width > 0 );
00085 assert( Height > 0 );
00086 assert( MaxSpans > 0 );
00087
00088 SpanBuffer_Destroy();
00089
00090 SpanBuffer_MaxSpares = MaxSpans;
00091 SpanBuffer_LineCount = Height;
00092
00093 SpanBuffer_Lines = geRam_Allocate(sizeof(SpanBuffer_Span *) * Height);
00094 if (SpanBuffer_Lines == NULL)
00095 {
00096 geErrorLog_AddString( GE_ERR_MEMORY_RESOURCE,"Unable to create span buffer table",NULL);
00097 return GE_FALSE;
00098 }
00099
00100 SpanBuffer_Spares = geRam_Allocate(sizeof(SpanBuffer_Span) * MaxSpans);
00101 if (SpanBuffer_Lines == NULL)
00102 {
00103 geErrorLog_AddString(GE_ERR_MEMORY_RESOURCE ,"Unable to create spare span list",NULL);
00104 geRam_Free(SpanBuffer_Lines);
00105 SpanBuffer_Lines = NULL;
00106 return GE_FALSE;
00107 }
00108
00109 SpanBuffer_Segments = geRam_Allocate(sizeof(SpanBuffer_ClipSegment) * (Width/2) );
00110 if (SpanBuffer_Segments == NULL )
00111 {
00112 geErrorLog_AddString( GE_ERR_MEMORY_RESOURCE,"Unable to create span buffer clip segment list",NULL);
00113 geRam_Free(SpanBuffer_Lines);
00114 SpanBuffer_Lines = NULL;
00115 geRam_Free(SpanBuffer_Spares);
00116 SpanBuffer_Spares = NULL;
00117 return GE_FALSE;
00118 }
00119 SpanBuffer_Clear();
00120 return GE_TRUE;
00121 }
00122
00123 #if 0 // not used (yet)
00124 geBoolean SpanBuffer_Visible(int Line, int Left, int Right)
00125 {
00126 SpanBuffer_Span *S;
00127 assert( Line>=0 );
00128 assert( Line< SpanBuffer_LineCount );
00129 assert( Right>=Left );
00130
00131
00132 S = SpanBuffer_Lines[Line];
00133 while (S)
00134 {
00135 if (Left<S->Min)
00136 return GE_TRUE;
00137 if (Right<=S->Max)
00138 return GE_FALSE;
00139 S=S->Next;
00140 }
00141 return GE_TRUE;
00142 }
00143 #endif
00144
00145 int SpanBuffer_ClipAndAdd(int Line, int LeftStart, int Width)
00146 {
00147 SpanBuffer_Span *LastSpan;
00148 SpanBuffer_Span *NewSpan;
00149 SpanBuffer_Span *Span;
00150 SpanBuffer_ClipSegment *Segment;
00151 int Left = LeftStart;
00152 int Right = LeftStart + Width -1;
00153 int SegmentCount = 0;
00154 #pragma message("fix this off by one problem here and in the engine!")
00155 if (Line>=SpanBuffer_LineCount)
00156 return 0;
00157
00158 assert( Line >= 0 );
00159 assert( Line< SpanBuffer_LineCount );
00160 assert( Width >= 0 );
00161 assert( LeftStart >=0 );
00162
00163 Segment = &(SpanBuffer_Segments[0]);
00164 LastSpan = NULL;
00165 Span = SpanBuffer_Lines[Line];
00166
00167 while (Span)
00168 {
00169 if (Left < Span->Min)
00170 {
00171 if (Right<Span->Min)
00172 {
00173 break;
00174 }
00175 else
00176 {
00177 Segment->LeftOffset = Left - LeftStart;
00178 Segment->Width = Span->Min - Left;
00179 SegmentCount++;
00180 Segment++;
00181
00182 Span->Min = Left;
00183 if (LastSpan)
00184 {
00185 if (LastSpan->Max+1 == Span->Min)
00186 {
00187 LastSpan->Max = Span->Max;
00188 LastSpan->Next = Span->Next;
00189 Span = LastSpan;
00190
00191 }
00192 }
00193 }
00194 }
00195 if (Left <= Span->Max)
00196 {
00197 Left = Span->Max + 1;
00198 if (Left > Right)
00199 return SegmentCount;
00200 }
00201 LastSpan = Span;
00202 Span = Span->Next;
00203 }
00204
00205
00206 Segment->LeftOffset = Left - LeftStart;
00207 Segment->Width = Right - Left + 1;
00208 SegmentCount++;
00209
00210
00211 if (LastSpan)
00212 {
00213 if (LastSpan->Max+1 == Left)
00214 {
00215 LastSpan->Max = Right;
00216 }
00217 else
00218 {
00219 if (SpanBuffer_FirstSpare<SpanBuffer_MaxSpares)
00220 NewSpan = &(SpanBuffer_Spares[SpanBuffer_FirstSpare++]);
00221 else
00222 return SegmentCount;
00223 NewSpan->Min = Left;
00224 NewSpan->Max = Right;
00225 NewSpan->Next = Span;
00226 LastSpan->Next = NewSpan;
00227 }
00228 }
00229 else
00230 {
00231 if (SpanBuffer_FirstSpare<SpanBuffer_MaxSpares)
00232 NewSpan = &(SpanBuffer_Spares[SpanBuffer_FirstSpare++]);
00233 else
00234 return SegmentCount;
00235 NewSpan->Min = Left;
00236 NewSpan->Max = Right;
00237 NewSpan->Next = Span;
00238 SpanBuffer_Lines[Line] = NewSpan;
00239 }
00240
00241
00242 return SegmentCount;
00243 }
00244
00245
00246 #if 0
00247 void SpanBuffer_Test()
00248 {
00249 int Visible;
00250
00251 SpanBufferReset(1);
00252 Visible = SpanBuffer_Visible(0, 5,9 );
00253
00254 SpanBufferClipAndAdd(0,30,10);
00255 Visible = SpanBuffer_Visible(0, 5,9 );
00256 Visible = SpanBuffer_Visible(0, 30,40);
00257 Visible = SpanBuffer_Visible(0, 30,41);
00258 Visible = SpanBuffer_Visible(0, 29,40);
00259
00260 SpanBufferClipAndAdd(0,10,10);
00261 Visible = SpanBuffer_Visible(0, 10,50);
00262 Visible = SpanBuffer_Visible(0, 30,41);
00263 Visible = SpanBuffer_Visible(0, 50,60);
00264 Visible = SpanBuffer_Visible(0, 1,2);
00265 Visible = SpanBuffer_Visible(0, 15,35);
00266 Visible = SpanBuffer_Visible(0, 25,26);
00267
00268 Visible = SpanBuffer_Visible(0, 10,20);
00269 Visible = SpanBuffer_Visible(0, 30,40);
00270
00271
00272 SpanBufferClipAndAdd(0,5,50);
00273 Visible = SpanBuffer_Visible(0, 5,10);
00274 Visible = SpanBuffer_Visible(0, 60,70);
00275 Visible = SpanBuffer_Visible(0, 1,2);
00276
00277
00278 }
00279 #endif