3 * Common Driver/Filesystem Helper Functions
7 #include <api_drv_disk.h>
8 #include <api_drv_video.h>
13 //int DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length, tDrvUtil_Video_2DHandlers *Handlers, int SizeofHandlers);
14 //size_t DrvUtil_Video_WriteLFB(int Mode, tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t Length, void *Src);
15 void DrvUtil_Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour);
16 void DrvUtil_Video_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H);
19 tDrvUtil_Video_2DHandlers gDrvUtil_Stub_2DFunctions = {
21 DrvUtil_Video_2D_Fill,
26 // --- Video Driver Helpers ---
27 int DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length,
28 tDrvUtil_Video_2DHandlers *Handlers, int SizeofHandlers)
30 void *stream = Buffer;
37 stream = (void*)((tVAddr)stream + 1);
39 if(op > NUM_VIDEO_2DOPS) {
40 Log_Warning("DrvUtil",
41 "DrvUtil_Video_2DStream: Unknown operation %i",
46 if(op*sizeof(void*) > SizeofHandlers) {
47 Log_Warning("DrvUtil",
48 "DrvUtil_Video_2DStream: Driver does not support op %i",
55 case VIDEO_2DOP_NOP: break;
58 if(rem < 12) return Length-rem;
61 Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver"
62 " does not support VIDEO_2DOP_FILL");
68 ((Uint16*)stream)[0], ((Uint16*)stream)[1],
69 ((Uint16*)stream)[2], ((Uint16*)stream)[3],
74 stream = (void*)((tVAddr)stream + 12);
78 if(rem < 12) return Length-rem;
81 Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver"
82 " does not support VIDEO_2DOP_BLIT");
88 ((Uint16*)stream)[0], ((Uint16*)stream)[1],
89 ((Uint16*)stream)[2], ((Uint16*)stream)[3],
90 ((Uint16*)stream)[4], ((Uint16*)stream)[5]
94 stream = (void*)((tVAddr)stream + 12);
102 int DrvUtil_Video_WriteLFB(tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t Length, void *Buffer)
105 ENTER("pFBInfo xOffset xLength pBuffer",
106 Mode, FBInfo, Offset, Length, Buffer);
107 switch( FBInfo->BufferFormat )
109 case VIDEO_BUFFMT_TEXT:
111 tVT_Char *chars = Buffer;
112 int bytes_per_px = (FBInfo->Depth + 7) / 8;
113 int widthInChars = FBInfo->Width/giVT_CharWidth;
114 int heightInChars = FBInfo->Height/giVT_CharHeight;
117 LOG("bytes_per_px = %i", bytes_per_px);
118 LOG("widthInChars = %i, heightInChars = %i", widthInChars, heightInChars);
120 Length /= sizeof(tVT_Char); Offset /= sizeof(tVT_Char);
122 x = Offset % widthInChars; y = Offset / widthInChars;
123 LOG("x = %i, y = %i", x, y);
126 if(Offset > heightInChars * widthInChars) LEAVE_RET('i', 0);
127 if(y >= heightInChars) LEAVE_RET('i', 0);
129 if( Offset + Length > heightInChars*widthInChars )
131 Length = heightInChars*widthInChars - Offset;
134 dest = FBInfo->Framebuffer;
135 LOG("dest = %p", dest);
136 dest += y * giVT_CharHeight * FBInfo->Pitch;
137 LOG("dest = %p", dest);
139 for( i = 0; i < Length; i++ )
141 if( y >= heightInChars )
143 Log_Notice("DrvUtil", "Stopped at %i", i);
147 // LOG("chars->Ch=0x%x,chars->BGCol=0x%x,chars->FGCol=0x%x",
148 // chars->Ch, chars->BGCol, chars->FGCol);
152 dest + x*giVT_CharWidth*bytes_per_px, FBInfo->Depth, FBInfo->Pitch,
153 VT_Colour12toN(chars->BGCol, FBInfo->Depth),
154 VT_Colour12toN(chars->FGCol, FBInfo->Depth)
159 if( x >= widthInChars )
163 dest += FBInfo->Pitch*giVT_CharHeight;
164 LOG("dest = %p", dest);
167 Length = i * sizeof(tVT_Char);
171 case VIDEO_BUFFMT_FRAMEBUFFER:
172 if(FBInfo->Width*FBInfo->Height*4 < Offset+Length)
174 Log_Warning("DrvUtil", "DrvUtil_Video_WriteLFB - Framebuffer Overflow");
178 //TODO: Handle non 32-bpp framebuffer modes
179 if( FBInfo->Depth != 32 ) {
180 Log_Warning("DrvUtil", "DrvUtil_Video_WriteLFB - Don't support non 32-bpp FB mode");
185 //TODO: Handle pitch != Width*BytesPerPixel
186 // Copy to Frambuffer
187 dest = (Uint8 *)FBInfo->Framebuffer + Offset;
188 memcpy(dest, Buffer, Length);
191 case VIDEO_BUFFMT_2DSTREAM:
192 Length = DrvUtil_Video_2DStream(
193 FBInfo, Buffer, Length,
194 &gDrvUtil_Stub_2DFunctions, sizeof(gDrvUtil_Stub_2DFunctions)
206 void DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bitmap)
208 int csrX = Buf->CursorX, csrY = Buf->CursorY;
212 if( Buf->CursorBitmap )
214 DrvUtil_Video_RemoveCursor(Buf);
215 if( Bitmap->W != Buf->CursorBitmap->W || Bitmap->H != Buf->CursorBitmap->H )
217 free( Buf->CursorSaveBuf );
218 Buf->CursorSaveBuf = NULL;
220 free(Buf->CursorBitmap);
221 Buf->CursorBitmap = NULL;
224 // Check the new bitmap is valid
225 size = sizeof(tVideo_IOCtl_Bitmap) + Bitmap->W*Bitmap->H*4;
226 if( !CheckMem(Bitmap, size) ) {
227 Log_Warning("DrvUtil", "DrvUtil_Video_SetCursor: Bitmap (%p) invalid mem", Bitmap);
232 Buf->CursorBitmap = malloc( size );
233 memcpy(Buf->CursorBitmap, Bitmap, size);
235 // Restore cursor position
236 DrvUtil_Video_DrawCursor(Buf, csrX, csrY);
239 void DrvUtil_Video_DrawCursor(tDrvUtil_Video_BufInfo *Buf, int X, int Y)
241 int bytes_per_px = (Buf->Depth + 7) / 8;
244 int render_ox=0, render_oy=0, render_w, render_h;
246 if( X < 0 || Y < 0 ) return;
247 if( X >= Buf->Width || Y >= Buf->Height ) return;
249 if( !Buf->CursorBitmap ) return ;
251 X -= Buf->CursorBitmap->XOfs;
252 Y -= Buf->CursorBitmap->YOfs;
254 render_w = X > Buf->Width - Buf->CursorBitmap->W ? Buf->Width - X : Buf->CursorBitmap->W;
255 render_h = Y > Buf->Height - Buf->CursorBitmap->H ? Buf->Height - Y : Buf->CursorBitmap->H;
266 save_pitch = Buf->CursorBitmap->W * bytes_per_px;
268 dest = (void*)( (tVAddr)Buf->Framebuffer + Y * Buf->Pitch + X*bytes_per_px );
269 src = Buf->CursorBitmap->Data;
270 if( !Buf->CursorSaveBuf )
271 Buf->CursorSaveBuf = malloc( Buf->CursorBitmap->W*Buf->CursorBitmap->H*bytes_per_px );
272 // Save behind the cursor
273 for( y = render_oy; y < render_h; y ++ )
275 (Uint8*)Buf->CursorSaveBuf + y*save_pitch,
276 (Uint8*)dest + render_ox*bytes_per_px + y*Buf->Pitch,
277 render_w*bytes_per_px
283 src += render_oy * Buf->CursorBitmap->W;
284 for( y = render_oy; y < render_h; y ++ )
287 for(x = render_ox; x < render_w; x ++ )
289 if(src[x] & 0xFF000000)
292 ; // NOP, completely transparent
294 src += Buf->CursorBitmap->W;
295 dest = (void*)((Uint8*)dest + Buf->Pitch);
299 Log_Error("DrvUtil", "TODO: Implement non 32-bpp cursor");
306 void DrvUtil_Video_RemoveCursor(tDrvUtil_Video_BufInfo *Buf)
308 int bytes_per_px = (Buf->Depth + 7) / 8;
312 if( !Buf->CursorBitmap || Buf->CursorX == -1 ) return ;
314 if( !Buf->CursorSaveBuf )
317 save_pitch = Buf->CursorBitmap->W * bytes_per_px;
318 dest = (void*)( (tVAddr)Buf->Framebuffer + Buf->CursorY * Buf->Pitch + Buf->CursorX*bytes_per_px );
319 for( y = 0; y < Buf->CursorBitmap->H; y ++ )
320 memcpy( (Uint8*)dest + y*Buf->Pitch, (Uint8*)Buf->CursorSaveBuf + y*save_pitch, save_pitch);
325 void DrvUtil_Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour)
327 tDrvUtil_Video_BufInfo *FBInfo = Ent;
329 // TODO: Handle non-32bit modes
330 if( FBInfo->Depth != 32 ) return;
332 // TODO: Be less hacky
333 int pitch = FBInfo->Pitch/4;
334 Uint32 *buf = (Uint32*)FBInfo->Framebuffer + Y*pitch + X;
339 for(i=W;i--;tmp++) *tmp = Colour;
344 void DrvUtil_Video_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H)
346 tDrvUtil_Video_BufInfo *FBInfo = Ent;
347 int scrnpitch = FBInfo->Pitch;
348 int bytes_per_px = (FBInfo->Depth + 7) / 8;
349 int dst = DstY*scrnpitch + DstX;
350 int src = SrcY*scrnpitch + SrcX;
353 //Log("Vesa_2D_Blit: (Ent=%p, DstX=%i, DstY=%i, SrcX=%i, SrcY=%i, W=%i, H=%i)",
354 // Ent, DstX, DstY, SrcX, SrcY, W, H);
356 if(SrcX + W > FBInfo->Width) W = FBInfo->Width - SrcX;
357 if(DstX + W > FBInfo->Width) W = FBInfo->Width - DstX;
358 if(SrcY + H > FBInfo->Height) H = FBInfo->Height - SrcY;
359 if(DstY + H > FBInfo->Height) H = FBInfo->Height - DstY;
361 //Debug("W = %i, H = %i", W, H);
370 tmp = W*bytes_per_px;
371 for( tmp = W; tmp --; ) {
372 *((Uint8*)FBInfo->Framebuffer + dst + tmp) = *((Uint8*)FBInfo->Framebuffer + src + tmp);
379 memcpy((Uint8*)FBInfo->Framebuffer + dst, (Uint8*)FBInfo->Framebuffer + src, W*bytes_per_px);
384 //Log("Vesa_2D_Blit: RETURN");
388 // --- Disk Driver Helpers ---
389 Uint64 DrvUtil_ReadBlock(Uint64 Start, Uint64 Length, void *Buffer,
390 tDrvUtil_Callback ReadBlocks, Uint64 BlockSize, Uint Argument)
392 Uint8 tmp[BlockSize]; // C99
393 Uint64 block = Start / BlockSize;
394 int offset = Start - block * BlockSize;
395 int leading = BlockSize - offset;
400 ENTER("XStart XLength pBuffer pReadBlocks XBlockSize xArgument",
401 Start, Length, Buffer, ReadBlocks, BlockSize, Argument);
403 // Non aligned start, let's fix that!
406 if(leading > Length) leading = Length;
407 LOG("Reading %i bytes from Block1+%i", leading, offset);
408 ret = ReadBlocks(block, 1, tmp, Argument);
413 memcpy( Buffer, &tmp[offset], leading );
415 if(leading == Length) {
420 Buffer = (Uint8*)Buffer + leading;
422 num = ( Length - leading ) / BlockSize;
423 tailings = Length - num * BlockSize - leading;
426 num = Length / BlockSize;
427 tailings = Length % BlockSize;
430 // Read central blocks
433 LOG("Reading %i blocks", num);
434 ret = ReadBlocks(block, num, Buffer, Argument);
436 LEAVE('X', leading + ret * BlockSize);
437 return leading + ret * BlockSize;
441 // Read last tailing block
444 LOG("Reading %i bytes from last block", tailings);
446 Buffer = (Uint8*)Buffer + num * BlockSize;
447 ret = ReadBlocks(block, 1, tmp, Argument);
449 LEAVE('X', leading + num * BlockSize);
450 return leading + num * BlockSize;
452 memcpy( Buffer, tmp, tailings );
459 Uint64 DrvUtil_WriteBlock(Uint64 Start, Uint64 Length, void *Buffer,
460 tDrvUtil_Callback ReadBlocks, tDrvUtil_Callback WriteBlocks,
461 Uint64 BlockSize, Uint Argument)
463 Uint8 tmp[BlockSize]; // C99
464 Uint64 block = Start / BlockSize;
465 int offset = Start - block * BlockSize;
466 int leading = BlockSize - offset;
471 ENTER("XStart XLength pBuffer pReadBlocks pWriteBlocks XBlockSize xArgument",
472 Start, Length, Buffer, ReadBlocks, WriteBlocks, BlockSize, Argument);
474 // Non aligned start, let's fix that!
477 if(leading > Length) leading = Length;
478 LOG("Writing %i bytes to Block1+%i", leading, offset);
479 // Read a copy of the block
480 ret = ReadBlocks(block, 1, tmp, Argument);
486 memcpy( &tmp[offset], Buffer, leading );
488 ret = WriteBlocks(block, 1, tmp, Argument);
494 if(leading == Length) {
499 Buffer = (Uint8*)Buffer + leading;
501 num = ( Length - leading ) / BlockSize;
502 tailings = Length - num * BlockSize - leading;
505 num = Length / BlockSize;
506 tailings = Length % BlockSize;
509 // Read central blocks
512 LOG("Writing %i blocks", num);
513 ret = WriteBlocks(block, num, Buffer, Argument);
515 LEAVE('X', leading + ret * BlockSize);
516 return leading + ret * BlockSize;
520 // Read last tailing block
523 LOG("Writing %i bytes to last block", tailings);
525 Buffer = (Uint8*)Buffer + num * BlockSize;
527 ret = ReadBlocks(block, 1, tmp, Argument);
529 LEAVE('X', leading + num * BlockSize);
530 return leading + num * BlockSize;
533 memcpy( tmp, Buffer, tailings );
535 ret = WriteBlocks(block, 1, tmp, Argument);
537 LEAVE('X', leading + num * BlockSize);
538 return leading + num * BlockSize;