Jump to content
IGNORED

Pure C and Graphics on the Falcon


Recommended Posts

I'm reading the API reference for the graphics library that comes with Pure C and I'm a little confused. The "setpalette" function takes a color index from 0 to 15 and a hardware color value from 0 to 63. Does this mean that the Pure C libraries simply can not support the Falcon 256 color modes?

Edited by pixelmischief
Link to comment
Share on other sites

Ok. I'm lost. I've tried XBIOS calls to set the screen mode. I've tried the BGI libraries to set the screen mode. I can't even get the damn screen to blank, let alone draw a box; the graphical equivalent of "Hello, World!". Are there any "purists" out there who can give me a quick boost with Pure C shipped libs?

Link to comment
Share on other sites

I have no experience with C but Mr. Pink from Reservoir Gods wrote C library especial for games called GODLIB!

 

There is no question that the RG library is absolutely brilliant; and it is certainly my fallback position. The challenge with it, however, is that it is TOO brilliant. The learning curve to effectively use the RG library is as steep as learning to do simple things with native libraries. I'd like to crawl before I fly and the RG library is certainly the stuff that wings are made of. Also, using the RG library will mean accepting a great many assumptions concerning software design; like naming conventions and templating strategies. I'd like to take crack at developing something on my own terms, making the design decisions that I find elegant.

Link to comment
Share on other sites

If you want to draw any gfx like boxes, circles, and such, first open a virtual work station with v_opnvwk(). You have to request a VDI handle before you can draw anything on the screen with the VDI gfx commands.

 

Yes! Right before I went to bed last night, my brain lit on a pattern that I think will cover it.

 

- create a mode integer from bit pattern

- get a screen size (long) from getscreensize()

- malloc() a drawing surface

- malloc() a display surface

- setscreen mode passing the drawing and display surfaces and mode integer

- get a VDI handle

- draw something in a while loop terminating on getchar()

 

Does that sound about right?

Link to comment
Share on other sites

 

Yes! Right before I went to bed last night, my brain lit on a pattern that I think will cover it.

 

- create a mode integer from bit pattern

- get a screen size (long) from getscreensize()

- malloc() a drawing surface

- malloc() a display surface

- setscreen mode passing the drawing and display surfaces and mode integer

- get a VDI handle

- draw something in a while loop terminating on getchar()

 

Does that sound about right?

 

If you are attempting to do off-screen bitmaps + VDI calls you will have to use NVDI calls. The standard Atari VDI doesn't support off screen drawing. Alternately, you could draw everything yourself, as it looks like you are not attempting to write something GEM friendly anyway.

Edited by lp060
Link to comment
Share on other sites

If you are attempting to do off-screen bitmaps + VDI calls you will have to use NVDI calls. The standard Atari VDI doesn't support off screen drawing. Alternately, you could draw everything yourself, as it looks like you are not attempting to write something GEM friendly anyway.

 

No, GEM friendliness is not an issue. The intended application is fullscreen 320x240x8BPP. Except for maybe some clearing routines, everything will be bitmapped graphics, not primitives. The reason my pseudo-code includes pointers to a drawing surface and a display surface is that the API for VsetScreen() explicitly requires each. Am I barking up the wrong tree on this?

Link to comment
Share on other sites

Ah, I was not sure initially what you were trying to do, it looked like some sort of double buffering technique. Just allocate one buffer for your screen and point both VsetScreen() pointers at it. Then the standard VDI will be ok drawing to it.

Link to comment
Share on other sites

Ah, I was not sure initially what you were trying to do, it looked like some sort of double buffering technique. Just allocate one buffer for your screen and point both VsetScreen() pointers at it. Then the standard VDI will be ok drawing to it.

 

Ok, But doesn't that defeat the function of the blitter? I've never coded graphics on the Atari (obviously), but back in the day, DOS ModeX coding was done by drawing to a back buffer and then, on sync, blitting it to the display surface. When I read the prototype for VsetScreen(), my brain matched it up with the blitter concept and assumed that was what was needed. I am going to follow your suggestion now, just to try to get something on the screen. BUt could you think about and maybe explore the concept I discussed?

Link to comment
Share on other sites

 

Ok, But doesn't that defeat the function of the blitter? I've never coded graphics on the Atari (obviously), but back in the day, DOS ModeX coding was done by drawing to a back buffer and then, on sync, blitting it to the display surface. When I read the prototype for VsetScreen(), my brain matched it up with the blitter concept and assumed that was what was needed. I am going to follow your suggestion now, just to try to get something on the screen. BUt could you think about and maybe explore the concept I discussed?

Probably that will work, physical versus logical addresses. However, the VDI isn't exactly the most efficient way to get the gfx drawn.

Link to comment
Share on other sites

 

Yes! Right before I went to bed last night, my brain lit on a pattern that I think will cover it.

 

- create a mode integer from bit pattern

- get a screen size (long) from getscreensize()

- malloc() a drawing surface

- malloc() a display surface

- setscreen mode passing the drawing and display surfaces and mode integer

- get a VDI handle

- draw something in a while loop terminating on getchar()

 

Does that sound about right?

 

Yes this is approximately what you want, if you want exclusive control over the display / framebuffer on a Falcon. Particularly important that you allocate the right amount of space in advance of changing the displaymode otherwise you'll trash memory. You should make sure the buffers are aligned to at least 4 bytes (on an ST, it would need 256 bytes - I usually prefer it as a rule of thumb). 4 byte alignment probably happens automatically with malloc but easy enough to make sure...

 

char *palloc = malloc(size+256);

pframebuf= (char*)(((int)palloc + 255) & ~255);

...

... do something, then exit

...

free(palloc); // not pframebuf!

 

 

When creating the modecode from the bitpattern, it's usually sufficient (at least to start with) to just get the old mode and mask off the unwanted bits, combining new ones for resolution and colour depth. This helps keep things happy on both VGA and RGB since those flags remain untouched.

 

Be aware that RGB and VGA modes can be different sizes (200 lines vs 240 lines) for what amounts to the same 'mode' and that other software (BlowUp, Videlity etc.) can change this as well - making it even more important to ask TOS how much memory needs alloc'd. Better not hardcode it to TOS resolution defaults - otherwise boom!

 

You'll also need to save the old display info and put it back on exiting, particularly if you're using a real machine :) Painful to have to reboot just to open the compiler editor again :)

 

 

You'll probably find it infinitely easier (more effort, but be less confused, and learn more) to just write directly to the framebuffer rather than go via the VDI, at least in chunky pixel truecolour mode.

 

1 word = 1 pixel. bytes per line = screen width * 2. easy! Bitplane modes are much more work to get used to coding for, but in the end its the same as an ST, just more planes...

 

VDI isn't hard to use at all - but depending on what level you fiddle with display settings it may not understand what changes you've made and results can be wrong or just crash. Same situation if VDI is not initialized properly. Learning curve there... most coders using exclusive access to the screen on a Falcon for performance graphics won't bother with the VDI stuff at all...

 

Hope that helps.

Link to comment
Share on other sites

You'll probably find it infinitely easier (more effort, but be less confused, and learn more) to just write directly to the framebuffer rather than go via the VDI, at least in chunky pixel truecolour mode.

Yeah, I think this is definitely the route I want to take. So, just to verify, I pass a back buffer and a display buffer to the mode setter, draw to the back, and blit. And the blit will automatically copy the frame from the back to the display. Am I right?

Link to comment
Share on other sites

Yeah, I think this is definitely the route I want to take. So, just to verify, I pass a back buffer and a display buffer to the mode setter, draw to the back, and blit. And the blit will automatically copy the frame from the back to the display. Am I right?

 

You can blit (or use a memcpy() to do the same job) and it will work, but these are old machines and moving that much memory takes ages - has to be done physically by the CPU or blitter, over the same 16bit bus.

 

The Ataris are better set up to perform a page flipping / surface flipping which is also a common method on PC in exclusive mode. Your physbase/logbase are your pages - the hardware shows you the contents of physbase and hides logbase. Change those pointers over and you'll see the other buffer. There are several ways to set the pointers - Vsetscreen is one of several XBios display calls available. Writing direct to the display HW registers is another way.

 

Really logbase is only needed by TOS/VDI if you're using those to draw to the backbuffer. If not, only physbase matters. You can write to the backbuffer yourself without informing TOS. But beware things like printf which go through TOS and will corrupt memory if logbase and VDI are not aware of whats happening.

Link to comment
Share on other sites

 

You can blit (or use a memcpy() to do the same job) and it will work, but these are old machines and moving that much memory takes ages - has to be done physically by the CPU or blitter, over the same 16bit bus.

 

The Ataris are better set up to perform a page flipping / surface flipping which is also a common method on PC in exclusive mode. Your physbase/logbase are your pages - the hardware shows you the contents of physbase and hides logbase. Change those pointers over and you'll see the other buffer. There are several ways to set the pointers - Vsetscreen is one of several XBios display calls available. Writing direct to the display HW registers is another way.

 

Really logbase is only needed by TOS/VDI if you're using those to draw to the backbuffer. If not, only physbase matters. You can write to the backbuffer yourself without informing TOS. But beware things like printf which go through TOS and will corrupt memory if logbase and VDI are not aware of whats happening.

 

Aaaaaaah. So just keep swapping the pointers between physbase and logbase. Yes, ok. Thanks!

Link to comment
Share on other sites

I think I'm pretty close to the most rudimentary construct from which to begin working, but it's not there yet. Please look at the code below and how it crashes and offer me some pointers (pun most definitely intended).

 

#include<stdio.h>
#include<stdlib.h>
#include<tos.h>

#define VsetScreen(laddr,paddr,mode) xbios(5,laddr,paddr,3,mode)
#define SCREEN_MODE_340X240X65536 276


void main()
{

	int previousScreenMode;
	int *previousLogicalBase;
	int *previousPhysicalBase;
	long newScreenSize;
	int *newSharedBase;
	char pressedKey;
	int videoMemoryLocationOffset;

	previousLogicalBase = Logbase();
	previousPhysicalBase = Physbase();

	newScreenSize = VgetSize( SCREEN_MODE_340X240X65536 );
	newSharedBase = malloc( newScreenSize );

	previousScreenMode = VsetScreen( newSharedBase, newSharedBase, SCREEN_MODE_340X240X65536 );

	for ( videoMemoryLocationOffset = 0 ; videoMemoryLocationOffset < newScreenSize ; ++videoMemoryLocationOffset )
	{
		*( newSharedBase + videoMemoryLocationOffset ) = 255;
	}
	
	while ( ( pressedKey = getchar() ) != 'q' )
	{
		Vsync();
	}

	VsetScreen( previousLogicalBase, previousPhysicalBase, previousScreenMode );

}

post-23588-0-39015600-1425209116_thumb.jpg

Edited by pixelmischief
Link to comment
Share on other sites

Much, much, much better. This code sets each pixel location's color to whatever the offset iterator is (0 to 76800). Now I'm trying to figure out how to convert the RGB 5:6:5 bit format into a 16-bit integer. Any help would be hot.

 

#include<stdio.h>
#include<stdlib.h>
#include<tos.h>

#define VsetScreen(laddr,paddr,mode) xbios(5,laddr,paddr,3,mode)
#define SCREEN_MODE_340X240X65536 276

void main()
{

	int previousScreenMode;
	long *previousLogicalBase;
	long *previousPhysicalBase;
	long newScreenSize;
	int *newSharedBase;
	char pressedKey;
	long pixelCount;
	long currentPixelOffset;


	previousLogicalBase = Logbase();
	previousPhysicalBase = Physbase();

	newScreenSize = VgetSize( SCREEN_MODE_340X240X65536 );
	newSharedBase = malloc( newScreenSize );

	previousScreenMode = VsetScreen( newSharedBase, newSharedBase, SCREEN_MODE_340X240X65536 );
	pixelCount = 76800;

	pressedKey = 0;
	while ( pressedKey != '\n' )
	{
		for ( currentPixelOffset = 0 ; currentPixelOffset < pixelCount ; ++currentPixelOffset )
		{
			*( newSharedBase + currentPixelOffset ) = currentPixelOffset;
		}
		Vsync();
		pressedKey = getchar();
	}

	VsetScreen( previousLogicalBase, previousPhysicalBase, previousScreenMode );

}

 

post-23588-0-65615400-1425221141_thumb.jpg

Edited by pixelmischief
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...