![]() |
![]() |
#1 |
Registered User
Join Date: May 2006
Location: Spain
Age: 42
Posts: 76
|
ScrollVPort double buffer problem with garbage pixels
Hello.
I'm working on a system friendly game engine for Amiga, from AmigaOS 2.0 to the new gen. compatible systems, I have tested my engine on MorphOS, EUAE and my Amiga 600. But I have a problem with my double buffer implementation, it uses ScrollVPort trick with a doubled screen height, it show some garbage pixels at the end of one of the buffers on real Amiga or emulators. I think that it could be related with overscan, but I figure out where is the problem, I can't find the reason, maybe someone can help me with my problem, this is a simple code showing my problem (compiled with SAS/C 6.58): Code:
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <libraries/lowlevel.h> #include <libraries/asl.h> #include <proto/asl.h> #include <proto/lowlevel.h> #include <proto/exec.h> #include <proto/intuition.h> #include <proto/graphics.h> #include <proto/dos.h> #include <exec/memory.h> #define DEPTH 8 struct Library *AslBase =NULL; UWORD__chip EmptyPointer[] = {0, 0, 0, 0}; int main(void) { struct ScreenModeRequester *screenReq; struct Screen *screen; struct Window *window; LONG width = 0, height = 0, frame = 0, frameOffset = 0, key = 0, x, y, n; AslBase =OpenLibrary("asl.library",38); if (AslBase) { screenReq = AllocAslRequest(ASL_ScreenModeRequest, NULL); AslRequestTags(screenReq, NULL); width = screenReq->sm_DisplayWidth; height=screenReq->sm_DisplayHeight; screen= OpenScreenTags(NULL, SA_DisplayID, screenReq->sm_DisplayID, SA_Left, 0, SA_Top, 0, SA_Width, width, SA_Height, height<<1, SA_Depth, DEPTH, // SA_Type, CUSTOMSCREEN, SA_Quiet, TRUE, SA_Overscan, OSCAN_STANDARD, SA_AutoScroll, FALSE, TAG_DONE); window =OpenWindowTags(NULL, WA_CustomScreen, screen, WA_Title, NULL, WA_Flags, WFLG_BORDERLESS | WFLG_REPORTMOUSE | WFLG_ACTIVATE, WA_IDCMP, 0, TAG_DONE); FreeAslRequest(screenReq); CloseLibrary(AslBase); } if (screen && window) { SetPointer(window, EmptyPointer, 1L, 1L, 0L, 0L); do { key = GetKey(); RectFill(&screen->RastPort, 0, frameOffset, width, frameOffset+height); frame ^= 1; frameOffset = frame*height; screen->ViewPort.RasInfo->RyOffset = frameOffset; ScrollVPort(&screen->ViewPort); WaitBOVP(&screen->ViewPort); } while (key != 69); CloseWindow(window); CloseScreen(screen); } return RETURN_OK; } ![]() Last edited by balrogsoft; 28 May 2014 at 20:04. |
![]() |
![]() |
#2 |
Registered User
Join Date: May 2006
Location: Spain
Age: 42
Posts: 76
|
I have found the solution on CyberAnim13.lha from aminet, it uses a ScrollVPort double buffer, and overscan was the problem, here is the correct source for a ScrollVPort, it works on MorphOS, EUAE, and my Amiga 600.
Code:
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <libraries/lowlevel.h> #include <libraries/asl.h> #include <proto/asl.h> #include <proto/lowlevel.h> #include <proto/exec.h> #include <proto/intuition.h> #include <proto/graphics.h> #include <proto/dos.h> #include <exec/memory.h> #define DEPTH 5 struct Library *AslBase =NULL; UWORD__chip EmptyPointer[] = {0, 0, 0, 0}; int main(void) { struct ScreenModeRequester *screenReq; struct Screen *screen; struct Window *window; LONG width = 0, height = 0, frame = 0, frameOffset = 0, key = 0, x, y, n; AslBase =OpenLibrary("asl.library",38); if (AslBase) { struct DimensionInfo dimsinfo; LONG oscan_height; void *handle; screenReq = AllocAslRequest(ASL_ScreenModeRequest, NULL); AslRequestTags(screenReq, NULL); width = screenReq->sm_DisplayWidth; height= screenReq->sm_DisplayHeight; handle = FindDisplayInfo (screenReq->sm_DisplayID); GetDisplayInfoData (handle, (UBYTE *)&dimsinfo, sizeof(struct DimensionInfo), DTAG_DIMS, NULL); oscan_height = dimsinfo.MaxOScan.MaxY - dimsinfo.MaxOScan.MinY + 1; if (oscan_height > height) height =oscan_height; screen= OpenScreenTags(NULL, SA_DisplayID, screenReq->sm_DisplayID, SA_Left, 0, SA_Top, 0, SA_Width, width, SA_Height, height<<1, SA_Depth, DEPTH, SA_Type, CUSTOMSCREEN, SA_Draggable, FALSE, SA_Exclusive, TRUE, SA_AutoScroll,FALSE, TAG_DONE); window =OpenWindowTags(NULL, WA_CustomScreen, screen, WA_Title, NULL, WA_Flags, WFLG_BORDERLESS | WFLG_REPORTMOUSE | WFLG_ACTIVATE, WA_IDCMP, 0, TAG_DONE); FreeAslRequest(screenReq); CloseLibrary(AslBase); } if (screen && window) { SetPointer(window, EmptyPointer, 1L, 1L, 0L, 0L); do { key = GetKey(); RectFill(&screen->RastPort, 0, frameOffset, width, frameOffset+height); ScrollVPort(&screen->ViewPort); WaitBOVP(&screen->ViewPort); frame ^= 1; frameOffset = frame*height; screen->ViewPort.RasInfo->RyOffset = frameOffset; } while (key != 69); CloseWindow(window); CloseScreen(screen); } return RETURN_OK; } |
![]() |
![]() |
#3 |
Computer Nerd
Join Date: Sep 2007
Location: Rotterdam/Netherlands
Age: 48
Posts: 3,946
|
You should get rid of WaitBOVP, because it uses busy waiting. Better to setup a copper list that generates a copper interrupt at the bottom of the screen, and have an interrupt server signal your program.
|
![]() |
![]() |
#4 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,603
|
If you don't want to bother with user copperlists and chipset specific stuff, just use WaitTOF(), it does not busy wait and difference between WaitTOF() and WaitBOVP() will be only few scanlines in overscan modes. (and probably there is no difference in RTG modes)
|
![]() |
![]() |
#5 | ||
Registered User
Join Date: May 2006
Location: Spain
Age: 42
Posts: 76
|
Quote:
Quote:
My engine is not aimed to low end Amigas, it uses system functions for drawing operations to make it compatible with new gen systems. Its features are: Screen management (up to 8 bits depth only) with primitive gfx functions, chunky 2 planar support (via kalms c2p and WritePixelArray8 for CGFX). Software sprites, with background restoration, and simple sprite mask generation for blitting. Mod music support via ptreplay.library. Joystick support via lowlevel.library. I want to port my Engine to Android and other platforms, and develop games for Amiga and other platforms like Android and iPhone with the same source code. This is one example for my engine, I think it is pretty easy to use: Code:
if (bitmap_init() & joy_init() & music_init()) { Bitmap *bm = bm_create(WIDTH,HEIGHT,DEPTH); FrameBuffer *fb = fb_init(320, 256, 8); GraphicContext *gc = gc_createWithFrameBuffer(fb); GraphicContext *bm_gc = gc_createWithBitmap(bm); int x = 100, y = 100, fr = 0, key = 0, i, m = 0, cwidth = fb->width, cheight = fb->height; UBYTE *chunky = (UBYTE*)malloc(WIDTH*HEIGHT); for (y = 0; y < HEIGHT; y++) { for (x=0; x < WIDTH; x++) { chunky[y*WIDTH+x] = (x-y)&63; } } m=0; do { key = GetKey(); // C2P to bitmap gc_c2p(bm_gc, chunky, 0, 0, WIDTH, HEIGHT, TRUE); // C2P to screen bitmap gc_c2p(gc, chunky, 100, 130, WIDTH, HEIGHT, TRUE); gc_drawBitmap(gc, bm, 0, 0, 0); gc_setColor(gc, 11); gc_fillRect(gc, 10+(m%64),20, 10, 10); m++; fb_flush(fb); } while (key != 69); free(chunky); gc_dealloc(gc); gc_dealloc(bm_gc); fb_dealloc(fb); bm_dealloc(bm); } joy_dealloc(); bitmap_dealloc(); music_dealloc(); |
||
![]() |
![]() |
#6 |
Computer Nerd
Join Date: Sep 2007
Location: Rotterdam/Netherlands
Age: 48
Posts: 3,946
|
Yeah, try it. WaitBOVP is a huge waste of CPU cycles, and should not ever be used on Amiga hardware.
|
![]() |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
Double PAL / Double NTSC, oficially supported by WHDLoad... | Shoonay | project.WHDLoad | 3 | 15 May 2021 19:42 |
[PROBLEM] Amiga Forever 2012 R3 scales pixels weird - how do I adjust it? | KidCupcake | support.WinUAE | 11 | 05 December 2012 22:39 |
Keyboard buffer problem | Nut | Coders. General | 5 | 08 May 2012 15:53 |
Double buffer copper?? | h0ffman | Coders. General | 8 | 19 July 2011 19:10 |
Vsync Fullscreen and Double Buffer, incorrect frame rate? | rsn8887 | support.WinUAE | 1 | 07 April 2011 20:43 |
|
|