6 * - Common Driver/Filesystem Helper Functions
10 #include <api_drv_disk.h>
11 #include <api_drv_video.h>
16 //int DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length, tDrvUtil_Video_2DHandlers *Handlers, int SizeofHandlers);
17 //size_t DrvUtil_Video_WriteLFB(int Mode, tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t Length, void *Src);
18 //void DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bitmap);
19 //void DrvUtil_Video_DrawCursor(tDrvUtil_Video_BufInfo *Buf, int X, int Y);
20 void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf);
21 //void DrvUtil_Video_RemoveCursor(tDrvUtil_Video_BufInfo *Buf);
22 void DrvUtil_Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour);
23 void DrvUtil_Video_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H);
26 tDrvUtil_Video_2DHandlers gDrvUtil_Stub_2DFunctions = {
28 DrvUtil_Video_2D_Fill,
31 tVideo_IOCtl_Bitmap gDrvUtil_TextModeCursor = {
35 0, 0, 0 , 0, 0, 0, 0, 0,
36 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
37 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
38 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
39 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
40 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
41 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
42 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
43 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
44 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
45 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
46 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
47 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
48 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
49 0, 0, 0 , 0, 0, 0, 0, 0,
50 0, 0, 0 , 0, 0, 0, 0, 0
55 // --- Video Driver Helpers ---
56 int DrvUtil_Video_2DStream(void *Ent, const void *Buffer, int Length,
57 tDrvUtil_Video_2DHandlers *Handlers, int SizeofHandlers)
59 const Uint8 *stream = Buffer;
71 if(op > NUM_VIDEO_2DOPS) {
72 Log_Warning("DrvUtil",
73 "DrvUtil_Video_2DStream: Unknown operation %i",
78 if(op*sizeof(void*) > SizeofHandlers) {
79 Log_Warning("DrvUtil",
80 "DrvUtil_Video_2DStream: Driver does not support op %i",
87 case VIDEO_2DOP_NOP: break;
90 if(rem < 12) return Length-rem;
91 memcpy(tmp, stream, 6*2);
94 Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver"
95 " does not support VIDEO_2DOP_FILL");
101 tmp[0], tmp[1], tmp[2], tmp[3],
102 tmp[4] | ((Uint32)tmp[5] << 16)
109 case VIDEO_2DOP_BLIT:
110 if(rem < 12) return Length-rem;
112 if(!Handlers->Blit) {
113 Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver"
114 " does not support VIDEO_2DOP_BLIT");
120 tmp[0], tmp[1], tmp[2], tmp[3],
133 int DrvUtil_Video_WriteLFB(tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t Length, const void *Buffer)
136 const Uint32 *src = Buffer;
139 int bytes_per_px = (FBInfo->Depth + 7) / 8;
140 ENTER("pFBInfo xOffset xLength pBuffer",
141 FBInfo, Offset, Length, Buffer);
143 csr_x = FBInfo->CursorX;
144 csr_y = FBInfo->CursorY;
146 DrvUtil_Video_RemoveCursor(FBInfo);
148 switch( FBInfo->BufferFormat )
150 case VIDEO_BUFFMT_TEXT:
152 const tVT_Char *chars = Buffer;
153 int widthInChars = FBInfo->Width/giVT_CharWidth;
154 int heightInChars = FBInfo->Height/giVT_CharHeight;
157 LOG("bytes_per_px = %i", bytes_per_px);
158 LOG("widthInChars = %i, heightInChars = %i", widthInChars, heightInChars);
160 Length /= sizeof(tVT_Char); Offset /= sizeof(tVT_Char);
162 x = Offset % widthInChars; y = Offset / widthInChars;
163 LOG("x = %i, y = %i", x, y);
166 if(Offset > heightInChars * widthInChars) LEAVE_RET('i', 0);
167 if(y >= heightInChars) LEAVE_RET('i', 0);
169 if( Offset + Length > heightInChars*widthInChars )
171 Length = heightInChars*widthInChars - Offset;
174 dest = FBInfo->Framebuffer;
175 LOG("dest = %p", dest);
176 dest += y * giVT_CharHeight * FBInfo->Pitch;
177 LOG("dest = %p", dest);
179 for( i = 0; i < Length; i++ )
181 if( y >= heightInChars )
183 Log_Notice("DrvUtil", "Stopped at %i", i);
189 dest + x*giVT_CharWidth*bytes_per_px, FBInfo->Depth, FBInfo->Pitch,
190 VT_Colour12toN(chars->BGCol, FBInfo->Depth),
191 VT_Colour12toN(chars->FGCol, FBInfo->Depth)
196 if( x >= widthInChars )
200 dest += FBInfo->Pitch*giVT_CharHeight;
201 LOG("dest = %p", dest);
204 Length = i * sizeof(tVT_Char);
208 case VIDEO_BUFFMT_FRAMEBUFFER:
209 if(FBInfo->Width*FBInfo->Height*4 < Offset+Length)
211 Log_Warning("DrvUtil", "DrvUtil_Video_WriteLFB - Framebuffer Overflow");
215 switch(FBInfo->Depth)
219 Log_Warning("DrvUtil", "TODO: Support 15/16 bpp modes in LFB write");
222 x = Offset % FBInfo->Width;
223 y = Offset / FBInfo->Width;
224 dest = (Uint8*)FBInfo->Framebuffer + y*FBInfo->Pitch;
225 for( ; Length >= 4; Length -= 4 )
227 dest[x*3+0] = *src & 0xFF;
228 dest[x*3+1] = (*src >> 8) & 0xFF;
229 dest[x*3+2] = (*src >> 16) & 0xFF;
231 if(x == FBInfo->Width) {
232 dest += FBInfo->Pitch;
238 // Copy to Frambuffer
239 if( FBInfo->Pitch != FBInfo->Width*4 )
242 // Pitch isn't 4*Width
243 x = Offset % FBInfo->Width;
244 y = Offset / FBInfo->Height;
246 px = (Uint32*)FBInfo->Framebuffer + y*FBInfo->Pitch/4;
248 for( ; Length >= 4; Length -= 4, x )
251 if( x == FBInfo->Width ) {
259 dest = (Uint8 *)FBInfo->Framebuffer + Offset;
260 memcpy(dest, Buffer, Length);
264 Log_Warning("DrvUtil", "DrvUtil_Video_WriteLFB - Unknown bit depthn %i", FBInfo->Depth);
269 case VIDEO_BUFFMT_2DSTREAM:
270 Length = DrvUtil_Video_2DStream(
271 FBInfo, Buffer, Length,
272 &gDrvUtil_Stub_2DFunctions, sizeof(gDrvUtil_Stub_2DFunctions)
281 DrvUtil_Video_DrawCursor(FBInfo, csr_x, csr_y);
287 int DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bitmap)
289 int csrX = Buf->CursorX, csrY = Buf->CursorY;
292 ENTER("pBuf pBitmap", Buf, Bitmap);
295 if( Buf->CursorBitmap )
297 LOG("Clearing old cursor");
298 DrvUtil_Video_RemoveCursor(Buf);
299 if( !Bitmap || Bitmap->W != Buf->CursorBitmap->W || Bitmap->H != Buf->CursorBitmap->H )
301 free( Buf->CursorSaveBuf );
302 Buf->CursorSaveBuf = NULL;
304 if( Buf->CursorBitmap != &gDrvUtil_TextModeCursor)
305 free(Buf->CursorBitmap);
306 Buf->CursorBitmap = NULL;
309 // If the new bitmap is null, disable drawing
318 // Sanity check the bitmap
319 LOG("Sanity checking plox");
320 if( !CheckMem(Bitmap, sizeof(*Bitmap)) || !CheckMem(Bitmap->Data, Bitmap->W*Bitmap->H*sizeof(Uint32)) )
322 Log_Warning("DrvUtil", "DrvUtil_Video_SetCursor: Bitmap (%p) is in invalid memory", Bitmap);
328 // Don't take a copy of the DrvUtil provided cursor
329 if( Bitmap == &gDrvUtil_TextModeCursor )
331 LOG("No copy (provided cursor)");
332 Buf->CursorBitmap = Bitmap;
337 size = sizeof(tVideo_IOCtl_Bitmap) + Bitmap->W*Bitmap->H*4;
340 Buf->CursorBitmap = malloc( size );
341 memcpy(Buf->CursorBitmap, Bitmap, size);
344 // Restore cursor position
346 DrvUtil_Video_DrawCursor(Buf, csrX, csrY);
351 void DrvUtil_Video_DrawCursor(tDrvUtil_Video_BufInfo *Buf, int X, int Y)
353 int render_ox=0, render_oy=0, render_w, render_h;
355 ENTER("pBuf iX iY", Buf, X, Y);
356 DrvUtil_Video_RemoveCursor(Buf);
358 // X < 0 disables the cursor
366 if( X < 0 || Y < 0 || X >= Buf->Width || Y >= Buf->Height ) {
371 // Ensure the cursor is enabled
372 if( !Buf->CursorBitmap ) {
377 // Save cursor position (for changing the bitmap)
378 Buf->CursorX = X; Buf->CursorY = Y;
379 // Apply cursor's center offset
380 X -= Buf->CursorBitmap->XOfs;
381 Y -= Buf->CursorBitmap->YOfs;
383 // Get the width of the cursor on screen (clipping to right/bottom edges)
384 render_w = X > Buf->Width - Buf->CursorBitmap->W ? Buf->Width - X : Buf->CursorBitmap->W;
385 render_h = Y > Buf->Height - Buf->CursorBitmap->H ? Buf->Height - Y : Buf->CursorBitmap->H;
387 // Clipp to left/top edges
388 if(X < 0) { render_ox = -X; X = 0; }
389 if(Y < 0) { render_oy = -Y; Y = 0; }
392 Buf->CursorRenderW = render_w; Buf->CursorRenderH = render_h;
393 Buf->CursorDestX = X; Buf->CursorDestY = Y;
394 Buf->CursorReadX = render_ox; Buf->CursorReadY = render_oy;
396 LOG("%ix%i at %i,%i offset %i,%i",
397 render_w, render_h, X, Y, render_ox, render_oy);
399 // Call render routine
400 DrvUtil_Video_RenderCursor(Buf);
404 void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf)
406 int src_x = Buf->CursorReadX, src_y = Buf->CursorReadY;
407 int render_w = Buf->CursorRenderW, render_h = Buf->CursorRenderH;
408 int dest_x = Buf->CursorDestX, dest_y = Buf->CursorDestY;
409 int bytes_per_px = (Buf->Depth + 7) / 8;
410 int save_pitch = Buf->CursorBitmap->W * bytes_per_px;
415 dest = (Uint8*)Buf->Framebuffer + dest_y*Buf->Pitch + dest_x*bytes_per_px;
416 src = Buf->CursorBitmap->Data + src_y * Buf->CursorBitmap->W + src_x;
418 LOG("dest = %p, src = %p", dest, src);
420 // Allocate save buffer if not already
421 if( !Buf->CursorSaveBuf )
422 Buf->CursorSaveBuf = malloc( Buf->CursorBitmap->W*Buf->CursorBitmap->H*bytes_per_px );
425 // Save behind the cursor
426 for( y = 0; y < render_h; y ++ )
428 (Uint8*)Buf->CursorSaveBuf + y*save_pitch,
429 (Uint8*)dest + y*Buf->Pitch,
430 render_w*bytes_per_px
438 Log_Warning("DrvUtil", "TODO: Support 15/16 bpp modes in cursor draw");
441 LOG("24-bit render");
442 for( y = 0; y < render_h; y ++ )
446 for(x = 0; x < render_w; x ++, px += 3)
448 Uint32 value = src[x];
449 // TODO: Should I implement alpha blending?
450 if(value & 0xFF000000)
452 px[0] = value & 0xFF;
453 px[1] = (value >> 8) & 0xFF;
454 px[2] = (value >> 16) & 0xFF;
459 src += Buf->CursorBitmap->W;
460 dest = (Uint8*)dest + Buf->Pitch;
464 LOG("32-bit render");
465 for( y = 0; y < render_h; y ++ )
469 for(x = 0; x < render_w; x ++, px ++)
471 Uint32 value = src[x];
472 // TODO: Should I implement alpha blending?
473 if(value & 0xFF000000)
476 ; // NOP, completely transparent
478 LOG("row %i/%i (%p-%P) done", y+1, render_h, dest, MM_GetPhysAddr(dest));
479 src += Buf->CursorBitmap->W;
480 dest = (Uint8*)dest + Buf->Pitch;
484 Log_Error("DrvUtil", "RenderCursor - Unknown bit depth %i", Buf->Depth);
490 void DrvUtil_Video_RemoveCursor(tDrvUtil_Video_BufInfo *Buf)
492 int bytes_per_px = (Buf->Depth + 7) / 8;
496 // Just a little sanity
497 if( !Buf->CursorBitmap || Buf->CursorX == -1 ) return ;
498 if( !Buf->CursorSaveBuf ) return ;
500 // Debug("DrvUtil_Video_RemoveCursor: (Buf=%p) dest_x=%i, dest_y=%i", Buf, Buf->CursorDestX, Buf->CursorDestY);
503 save_pitch = Buf->CursorBitmap->W * bytes_per_px;
504 dest = (Uint8*)Buf->Framebuffer + Buf->CursorDestY * Buf->Pitch + Buf->CursorDestX*bytes_per_px;
505 src = Buf->CursorSaveBuf;
507 // Copy each line back
508 for( y = 0; y < Buf->CursorRenderH; y ++ )
510 memcpy( dest, src, Buf->CursorRenderW * bytes_per_px );
515 // Set the cursor as removed
519 void DrvUtil_Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour)
521 tDrvUtil_Video_BufInfo *FBInfo = Ent;
523 // TODO: Handle non-32bit modes
524 if( FBInfo->Depth != 32 ) return;
526 // TODO: Be less hacky
527 int pitch = FBInfo->Pitch/4;
528 Uint32 *buf = (Uint32*)FBInfo->Framebuffer + Y*pitch + X;
533 for(i=W;i--;tmp++) *tmp = Colour;
538 void DrvUtil_Video_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H)
540 tDrvUtil_Video_BufInfo *FBInfo = Ent;
541 int scrnpitch = FBInfo->Pitch;
542 int bytes_per_px = (FBInfo->Depth + 7) / 8;
543 int dst = DstY*scrnpitch + DstX;
544 int src = SrcY*scrnpitch + SrcX;
547 //Log("Vesa_2D_Blit: (Ent=%p, DstX=%i, DstY=%i, SrcX=%i, SrcY=%i, W=%i, H=%i)",
548 // Ent, DstX, DstY, SrcX, SrcY, W, H);
550 if(SrcX + W > FBInfo->Width) W = FBInfo->Width - SrcX;
551 if(DstX + W > FBInfo->Width) W = FBInfo->Width - DstX;
552 if(SrcY + H > FBInfo->Height) H = FBInfo->Height - SrcY;
553 if(DstY + H > FBInfo->Height) H = FBInfo->Height - DstY;
555 //Debug("W = %i, H = %i", W, H);
564 tmp = W*bytes_per_px;
565 for( tmp = W; tmp --; ) {
566 *((Uint8*)FBInfo->Framebuffer + dst + tmp) = *((Uint8*)FBInfo->Framebuffer + src + tmp);
570 else if(W == FBInfo->Width && FBInfo->Pitch == FBInfo->Width*bytes_per_px) {
571 memmove((Uint8*)FBInfo->Framebuffer + dst, (Uint8*)FBInfo->Framebuffer + src, H*FBInfo->Pitch);
576 memcpy((Uint8*)FBInfo->Framebuffer + dst, (Uint8*)FBInfo->Framebuffer + src, W*bytes_per_px);
581 //Log("Vesa_2D_Blit: RETURN");
585 // --- Disk Driver Helpers ---
586 Uint64 DrvUtil_ReadBlock(Uint64 Start, Uint64 Length, void *Buffer,
587 tDrvUtil_Read_Callback ReadBlocks, Uint64 BlockSize, void *Argument)
589 Uint8 tmp[BlockSize]; // C99
590 Uint64 block = Start / BlockSize;
591 int offset = Start - block * BlockSize;
592 int leading = BlockSize - offset;
597 ENTER("XStart XLength pBuffer pReadBlocks XBlockSize pArgument",
598 Start, Length, Buffer, ReadBlocks, BlockSize, Argument);
600 // Non aligned start, let's fix that!
603 if(leading > Length) leading = Length;
604 LOG("Reading %i bytes from Block1+%i", leading, offset);
605 ret = ReadBlocks(block, 1, tmp, Argument);
610 memcpy( Buffer, &tmp[offset], leading );
612 if(leading == Length) {
617 Buffer = (Uint8*)Buffer + leading;
619 num = ( Length - leading ) / BlockSize;
620 tailings = Length - num * BlockSize - leading;
623 num = Length / BlockSize;
624 tailings = Length % BlockSize;
627 // Read central blocks
630 LOG("Reading %i blocks", num);
631 ret = ReadBlocks(block, num, Buffer, Argument);
633 LEAVE('X', leading + ret * BlockSize);
634 return leading + ret * BlockSize;
638 // Read last tailing block
641 LOG("Reading %i bytes from last block", tailings);
643 Buffer = (Uint8*)Buffer + num * BlockSize;
644 ret = ReadBlocks(block, 1, tmp, Argument);
646 LEAVE('X', leading + num * BlockSize);
647 return leading + num * BlockSize;
649 memcpy( Buffer, tmp, tailings );
656 Uint64 DrvUtil_WriteBlock(Uint64 Start, Uint64 Length, const void *Buffer,
657 tDrvUtil_Read_Callback ReadBlocks, tDrvUtil_Write_Callback WriteBlocks,
658 Uint64 BlockSize, void *Argument)
660 Uint8 tmp[BlockSize]; // C99
661 Uint64 block = Start / BlockSize;
662 int offset = Start - block * BlockSize;
663 int leading = BlockSize - offset;
668 ENTER("XStart XLength pBuffer pReadBlocks pWriteBlocks XBlockSize pArgument",
669 Start, Length, Buffer, ReadBlocks, WriteBlocks, BlockSize, Argument);
671 // Non aligned start, let's fix that!
674 if(leading > Length) leading = Length;
675 LOG("Writing %i bytes to Block1+%i", leading, offset);
676 // Read a copy of the block
677 ret = ReadBlocks(block, 1, tmp, Argument);
683 memcpy( &tmp[offset], Buffer, leading );
685 ret = WriteBlocks(block, 1, tmp, Argument);
691 if(leading == Length) {
696 Buffer = (Uint8*)Buffer + leading;
698 num = ( Length - leading ) / BlockSize;
699 tailings = Length - num * BlockSize - leading;
702 num = Length / BlockSize;
703 tailings = Length % BlockSize;
706 // Read central blocks
709 LOG("Writing %i blocks", num);
710 ret = WriteBlocks(block, num, Buffer, Argument);
712 LEAVE('X', leading + ret * BlockSize);
713 return leading + ret * BlockSize;
717 // Read last tailing block
720 LOG("Writing %i bytes to last block", tailings);
722 Buffer = (Uint8*)Buffer + num * BlockSize;
724 ret = ReadBlocks(block, 1, tmp, Argument);
726 LEAVE('X', leading + num * BlockSize);
727 return leading + num * BlockSize;
730 memcpy( tmp, Buffer, tailings );
732 ret = WriteBlocks(block, 1, tmp, Argument);
734 LEAVE('X', leading + num * BlockSize);
735 return leading + num * BlockSize;