Jump to content



Photo
- - - - -

Request: Tutorial on Greyscales


  • Please log in to reply
24 replies to this topic

#1 SebHoll

SebHoll

    Newbie

  • Members
  • Pip
  • 19 posts
  • Gender:Male

  • Calculators:
    FX-9860G

Posted 19 September 2007 - 02:38 PM

I've been meaning to have a look into greyscales on the FX-9860G, and, after having a look at the greyscale commands in Revolution-FX, I'm non the wiser... :? Would anyone be able to write a short introduction to greyscales and how to use them in Casio C add-ins?

Thanks in advance,

SebHoll

#2 kucalc

kucalc

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1422 posts
  • Gender:Male
  • Location:USA
  • Interests:Programming: C/C++, Fortran, LISP, COBOL 85 Standard, PHP, x86 and SH3 Assembly

    Computer graphics

  • Calculators:
    fx-9860G / fx-7400G Plus / Algebra FX 2.0+ / fx-9770G / CFX-9850G / CFX-9850GB+ / TI-89 / TI-nSpire

Posted 19 September 2007 - 11:55 PM

I'm assuming you already know how to store bitmaps into a array. Here's a example of a 8x8 sprite to jog some memory:
char checker_pattern[8] = { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 };
(A checkered box)

Well ok, if you know how to organize and store bitmaps then let's move on. Grayscales in fx-9860 work by "flipping" buffers. If you every played with those flip books, they create some sort of animation when you're flipping through the pages. Well, in the fx-9860, either two buffers or three are "flipped" through. If you don't know what buffers are, just pretend they're like sheets of paper. One buffer = 1 sheet of paper. 2 buffers = 2 sheets of paper. And just like paper, you can draw whatever you want onto a buffer. One each buffer, only black or white can be drawn. These two buffers are "flipped through" really fast that it makes your brain think your seeing gray.

With two buffers (with a, let's say for example a 40% first buffer and 60% second buffer):
  • Black + White = Light gray
  • White + Black = Dark gray
  • Black + Black = Black

Now let's apply this to code. Let's say we already got our sprites:
unsigned char box_one[8] = { 0xFF, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0xFF };
unsigned char box_two[8] = { 0xFF, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0xFF };

We also need to declare our buffers (or our "sheets of paper" to draw on):
unsigned char buffer1[1024];
unsigned char buffer2[1024];

Initialize the grayscale engine and tell it which buffers you are using:
GrayInit(3273, 1454);
GrayLinkBuffers(buffer1, buffer2);

And draw our sprites onto our buffers (or "sheets of paper"):
while (IsKeyDown(KEY_CTRL_EXIT) != 1) {
	DrawSprite8(60, 28, buffer1, box_one, 0);
	DrawSprite8(60, 28, buffer2, box_two, 0);
}

For the whole program:
#include "fxlib.h"
#include "stdio.h"
#include "revolution.h"

int AddIn_main(int isAppli, unsigned short OptionNum)
{
	unsigned char buffer1[1024];
	unsigned char buffer2[1024];

	unsigned char box_one[8] = { 0xFF, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0xFF };
	unsigned char box_two[8] = { 0xFF, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0xFF };
	
	memset(&buffer1, 0, 1024);
	memset(&buffer2, 0, 1024);

	GrayInit(3273, 1454);
	GrayLinkBuffers(buffer1, buffer2);

	while (IsKeyDown(KEY_CTRL_EXIT) != 1) {
		DrawSprite8(60, 28, buffer1, box_one, 0);
		DrawSprite8(60, 28, buffer2, box_two, 0);
	}

	Reset_Calc();
	return 0;
}

#pragma section _BR_Size
unsigned long BR_Size;
#pragma section


#pragma section _TOP

int InitializeSystem(int isAppli, unsigned short OptionNum)
{
	return INIT_ADDIN_APPLICATION(isAppli, OptionNum);
}

#pragma section


#3 SebHoll

SebHoll

    Newbie

  • Members
  • Pip
  • 19 posts
  • Gender:Male

  • Calculators:
    FX-9860G

Posted 20 September 2007 - 08:29 AM

Thanks kucalc - that's a great help! I have a few more questions though...

  • Does the constant flipping of these buffers cause a significant loss of speed?
  • Why do you have to keep drawing the sprites to the buffers in the main loop? Surely when they are drawn once, they stay there, right?
  • How do you use more buffers to obtain more shades of grey, and is there a limit to how many buffers can be used?
  • Do you have to be careful about drawing while a buffer is being shown or not? (I have used Double-Buffering in game programming before, and am all to aware of these types of problems). ;)

Cheers

SebHoll

#4 kucalc

kucalc

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1422 posts
  • Gender:Male
  • Location:USA
  • Interests:Programming: C/C++, Fortran, LISP, COBOL 85 Standard, PHP, x86 and SH3 Assembly

    Computer graphics

  • Calculators:
    fx-9860G / fx-7400G Plus / Algebra FX 2.0+ / fx-9770G / CFX-9850G / CFX-9850GB+ / TI-89 / TI-nSpire

Posted 20 September 2007 - 01:18 PM

What are the 'magic numbers' in the GreyInit() function, and how do you choose them?

The magic numbers specify how long each buffer is to be displayed. These values are found by error and trial by searching which values look good. If one number is larger than the other, than that buffer gets displayed longer than the other. If both values are the same, than you get a 1 shade of gray,

Does the constant flipping of these buffers cause a significant loss of speed?

I don't know it's a significant loss, but there is some loss to do the flipping of buffers. If you look in MLC and tried out it's games, you still have some pretty fast games that use grayscales.

How do you use more buffers to obtain more shades of grey, and is there a limit to how many buffers can be used?

Having more buffers let's you have more combinations like:
Black + Black + White = Very dark gray
Black + White + Black = Dark gray
Black + White + White = Light gray
....

The Revolution-FX engine only allows up to 3 buffers. Using 3 buffers will be a bit more tricky though.

Do you have to be careful about drawing while a buffer is being shown or not?

No, not really. The chances that the buffer you are drawing onto is being drawn to the screen, is very very minimal.

Why do you have to keep drawing the sprites to the buffers in the main loop? Surely when they are drawn once, they stay there, right?

Yes, they stay there. They don't have to be in the main loop, I just did that because I don't want a empty loop as there is nothing else to do. :)

#5 SebHoll

SebHoll

    Newbie

  • Members
  • Pip
  • 19 posts
  • Gender:Male

  • Calculators:
    FX-9860G

Posted 20 September 2007 - 02:42 PM

OK, thanks. Just to clarify, if the flipping of the buffers done automatically, behind the scenes. All we have to do is draw to them?

Edit: I've just tried you code example above by copying and pasting it into a new project in the official Casio SDK, and although it builds OK, the emulator throws an unspecified exception error when you select the add-in from the main-menu. :|

#6 Andreas B

Andreas B

    Casio Freak

  • Members
  • PipPipPipPip
  • 160 posts
  • Gender:Male
  • Location:Norway

  • Calculators:
    fx-9860G SD

Posted 20 September 2007 - 07:22 PM

OK, thanks. Just to clarify, if the flipping of the buffers done automatically, behind the scenes. All we have to do is draw to them?

Yes.

If I have understood it correctly: An interrupt a piece of code that is run whenever the processor is 'interrupted' ;). It could be interrupted by a change on its IO ports or a change in its internal components, like the timer. The timer can interrupt the processor whenever the timer you set has expired, and runs the code you tells it to run. In RevFX's case, this code displays 'the other buffer' and sets an appropriate timeout for the next interrupt to happen.

#7 SebHoll

SebHoll

    Newbie

  • Members
  • Pip
  • 19 posts
  • Gender:Male

  • Calculators:
    FX-9860G

Posted 20 September 2007 - 08:19 PM

Thanks andreas!

Now, can anyone point out why kucalc's greyscale code example above won't run? :)

#8 kucalc

kucalc

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1422 posts
  • Gender:Male
  • Location:USA
  • Interests:Programming: C/C++, Fortran, LISP, COBOL 85 Standard, PHP, x86 and SH3 Assembly

    Computer graphics

  • Calculators:
    fx-9860G / fx-7400G Plus / Algebra FX 2.0+ / fx-9770G / CFX-9850G / CFX-9850GB+ / TI-89 / TI-nSpire

Posted 20 September 2007 - 11:16 PM

It should work on the calculator. It doesn't work in the emulator, because the emulator doesn't completely emulate the exact fx-9860G.

#9 SebHoll

SebHoll

    Newbie

  • Members
  • Pip
  • 19 posts
  • Gender:Male

  • Calculators:
    FX-9860G

Posted 21 September 2007 - 08:24 AM

If it doesn't work in the emulator, isn't that going to make add-in development almost impossible. It would take ages to keep on transferring it to the calculator to test new builds... :|

#10 kucalc

kucalc

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1422 posts
  • Gender:Male
  • Location:USA
  • Interests:Programming: C/C++, Fortran, LISP, COBOL 85 Standard, PHP, x86 and SH3 Assembly

    Computer graphics

  • Calculators:
    fx-9860G / fx-7400G Plus / Algebra FX 2.0+ / fx-9770G / CFX-9850G / CFX-9850GB+ / TI-89 / TI-nSpire

Posted 21 September 2007 - 12:52 PM

I guess it depends on your level of programming. MLC is I say is a pretty complex program, though it only took me 3 day to write a functioning build, I didn't need to use a emulator to write MLC. One way to bypass the emulator is to emulate and run the program in your head. That's what I do, the CASIO emulator is often just way too slow. Another alternative is to write our own emulator, a community emulator.

#11 SebHoll

SebHoll

    Newbie

  • Members
  • Pip
  • 19 posts
  • Gender:Male

  • Calculators:
    FX-9860G

Posted 21 September 2007 - 08:32 PM

I guess it depends on your level of programming. MLC is I say is a pretty complex program, though it only took me 3 day to write a functioning build, I didn't need to use a emulator to write MLC. One way to bypass the emulator is to emulate and run the program in your head. That's what I do, the CASIO emulator is often just way too slow. Another alternative is to write our own emulator, a community emulator.

:shock: Although I could probably "emulate in my head" in my native BASIC programming languages, C is completely new to me and it's hit and miss whether I've remembered to comply to it's strict (and sometimes pedantic :D ) syntax rules. I'm just thankful whether it will build, as usually if I get it to that stage, the logic is fine... I suppose therefore it could be feasible to create an add-in thins way, but I think I'm quite a way off being able to develop a serious application under those conditions...

Another alternative is to write our own emulator, a community emulator.

:shock: :shock: :shock: I wouldn't even know where to start with something like that! I would imagine it would be really complicated though... :P

#12 Andreas B

Andreas B

    Casio Freak

  • Members
  • PipPipPipPip
  • 160 posts
  • Gender:Male
  • Location:Norway

  • Calculators:
    fx-9860G SD

Posted 22 September 2007 - 04:31 PM

A third alternative would be to get xfer9860 going in Windows. When installed, you can run it with the right parameters (file name), and it will transfer your file of choice to the calculator. No syncing needed, and a lot quicker than FA-124. :P

#13 Fez

Fez

    Casio Freak

  • Members
  • PipPipPipPip
  • 162 posts
  • Gender:Male
  • Location:Australia

  • Calculators:
    Casio fx-9860G AU

Posted 12 November 2007 - 12:28 AM

int AddIn_main(int isAppli, unsigned short OptionNum)
{
const unsigned char Rifleone[] = {0x00,
0x00,0x00,0x00,0x07,0xE0,0x04,0x20,0x04,0x20,0x04,0x20,0x0F,0xF0,0x08,0x10,0x38,
0x1C,0x28,0x14,0x28,0x14,0x28,0x14,0x28,
0x14,0x28,0x14,0x28,0x14,0x28,0x14};

const unsigned char Rifletwo[] = {0x00,
0x00,0x00,0x00,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x0F,0xF0,0x0F,0xF0,0x3F,
0xFC,0x3F,0xFC,0x3F,0xFC,0x3F,0xFC,0x3F,
0xFC,0x3F,0xFC,0x3F,0xFC,0x3F,0xFC};
unsigned long buffer1[256] = { 0 };
unsigned long buffer2[256] = { 0 };
memset(&buffer1,0,256);
memset(&buffer2,0,256);
GrayLinkBuffers(&buffer1,&buffer2);
GrayInit(3273,1454);
	while(IsKeyDown(KEY_CTRL_MENU)==0){
		DrawSprite16(20,20,buffer1,Rifleone,0);
		DrawSprite16(20,20,buffer2,Rifletwo,0);
	}
}
I tried my hand at grayscales so I could draw a sprite for the 3D game. It's a rifle but this comes up with an error.
' ** L2310 (E) Undefined external symbol "_sgn" referenced in "graphics" '
But the thing is, _sgn is no where is this code.

#14 kucalc

kucalc

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1422 posts
  • Gender:Male
  • Location:USA
  • Interests:Programming: C/C++, Fortran, LISP, COBOL 85 Standard, PHP, x86 and SH3 Assembly

    Computer graphics

  • Calculators:
    fx-9860G / fx-7400G Plus / Algebra FX 2.0+ / fx-9770G / CFX-9850G / CFX-9850GB+ / TI-89 / TI-nSpire

Posted 12 November 2007 - 04:09 AM

:shock: Someone was asking me about the same thing this morning.

You'll have to switch back to v0.3 for now when using graphics. This should be fixed really soon.

#15 Fez

Fez

    Casio Freak

  • Members
  • PipPipPipPip
  • 162 posts
  • Gender:Male
  • Location:Australia

  • Calculators:
    Casio fx-9860G AU

Posted 12 November 2007 - 04:14 AM

Ok thanx. Just one more thing about the knew rev-fx. This might just be me but I done the same thing for Island wars as I did with RPS. But for some reason when it gets to sending the data the calc freezes. At first I thought it was because of something I had done and Ive been looking through it. But after grayscales, it might be in serial ports as well. I just thought you should know. XD

#16 kucalc

kucalc

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1422 posts
  • Gender:Male
  • Location:USA
  • Interests:Programming: C/C++, Fortran, LISP, COBOL 85 Standard, PHP, x86 and SH3 Assembly

    Computer graphics

  • Calculators:
    fx-9860G / fx-7400G Plus / Algebra FX 2.0+ / fx-9770G / CFX-9850G / CFX-9850GB+ / TI-89 / TI-nSpire

Posted 12 November 2007 - 04:27 AM

Ok, thanks for the bug reports. This will be looked into.

#17 E_net4

E_net4

    Casio Freak

  • Members
  • PipPipPipPip
  • 189 posts
  • Gender:Male
  • Location:Output("Error: Coord type not specified");
  • Interests:Programming 'n' stuff...

  • Calculators:
    CASIO fx 9860G SD

Posted 12 November 2007 - 09:06 PM

I guess it depends on your level of programming. MLC is I say is a pretty complex program, though it only took me 3 day to write a functioning build, I didn't need to use a emulator to write MLC. One way to bypass the emulator is to emulate and run the program in your head. That's what I do, the CASIO emulator is often just way too slow. Another alternative is to write our own emulator, a community emulator.

Umm, NO!
You already have too many projects in your head! :shock:

#18 kucalc

kucalc

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1422 posts
  • Gender:Male
  • Location:USA
  • Interests:Programming: C/C++, Fortran, LISP, COBOL 85 Standard, PHP, x86 and SH3 Assembly

    Computer graphics

  • Calculators:
    fx-9860G / fx-7400G Plus / Algebra FX 2.0+ / fx-9770G / CFX-9850G / CFX-9850GB+ / TI-89 / TI-nSpire

Posted 14 November 2007 - 04:51 AM

What do you mean? :shock:

#19 Fez

Fez

    Casio Freak

  • Members
  • PipPipPipPip
  • 162 posts
  • Gender:Male
  • Location:Australia

  • Calculators:
    Casio fx-9860G AU

Posted 14 November 2007 - 06:26 AM

doom/call of duty(which eva one you have chosen yet), MLC, Rev-FX, and i think thats all. If i had the work load of you i would cave. great job kucalc XD

#20 Fez

Fez

    Casio Freak

  • Members
  • PipPipPipPip
  • 162 posts
  • Gender:Male
  • Location:Australia

  • Calculators:
    Casio fx-9860G AU

Posted 28 November 2007 - 07:49 AM

With grayscales. I want to make a splash screen that has grayscales on it. Does grayscales work with draw all or do i have to make multiple 16x16 sprites to fill the screen?
I tried with draw all but the calc froze. I think it might be something to do with my code. ill see what i can do but I just wanna know. can i do it with the Drawall?

#21 kucalc

kucalc

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1422 posts
  • Gender:Male
  • Location:USA
  • Interests:Programming: C/C++, Fortran, LISP, COBOL 85 Standard, PHP, x86 and SH3 Assembly

    Computer graphics

  • Calculators:
    fx-9860G / fx-7400G Plus / Algebra FX 2.0+ / fx-9770G / CFX-9850G / CFX-9850GB+ / TI-89 / TI-nSpire

Posted 29 November 2007 - 12:40 AM

Actually, all you have to do is copy your splash screen to the gray buffers.
unsigned char splash_buffer1[1024];
unsigned char splash_buffer2[1024];

unsigned char buffer1[1024];
unsigned char buffer2[1024];

GrayLinkBuffers(buffer1, buffer2);
GrayInit(3280, 3280);

memcpy(buffer1, splash_buffer1, 1024);
memcpy(buffer2, splash_buffer2, 1024);


#22 Fez

Fez

    Casio Freak

  • Members
  • PipPipPipPip
  • 162 posts
  • Gender:Male
  • Location:Australia

  • Calculators:
    Casio fx-9860G AU

Posted 29 November 2007 - 02:23 AM

oh kool XD. I never even knew about memcpy XD

#23 Fez

Fez

    Casio Freak

  • Members
  • PipPipPipPip
  • 162 posts
  • Gender:Male
  • Location:Australia

  • Calculators:
    Casio fx-9860G AU

Posted 02 December 2007 - 02:59 AM

Is it possible to have Bdisp functions after using grayscsales. Because the menu doesnt work after woulds.It freezes. The calc freezes. I even used teh GrayEnd() function hoping that would work. I took out the splash screen with the gray in to see what would happen and then it worked. Whats going on XD
I have
void drawintro(){
const unsigned char main1[];

const unsigned char main2[];

char buffer1[1024];
char buffer2[1024];

memset(buffer1,0,1024);
memset(buffer2,0,1024);

GrayInit(3280,3280);
GrayLinkBuffers(buffer1,buffer2);

while(IsKeyDown(KEY_CTRL_AC)==0){
	memcpy(buffer1,main1,1024);
	memcpy(buffer2,main2,1024);
}
GrayEnd();
memset(buffer1,0,1024);
memset(buffer2,0,1024);
}

int AddIn_main(int isAppli, unsigned short OptionNum)
{
	drawintro();
	Bdisp_AllClr_DDVRAM();
	drawmain(0,0,1);
	SaveDisp(1);
	cursorx=1;
	cursory=1;
	while(1){
		RestoreDisp(1);
		if(cursorx==1&cursory==1){
			Bdisp_AreaReverseVRAM(2,17,63,26);
		}
		if(cursorx==1&cursory==2){
			Bdisp_AreaReverseVRAM(2,29,63,39);
		}
		if(cursorx==1&cursory==3){
			Bdisp_AreaReverseVRAM(2,42,63,52);
		}
		if(cursorx==2&cursory==1){
			Bdisp_AreaReverseVRAM(66,17,125,26);
		}
		if(cursorx==2&cursory==2){
			Bdisp_AreaReverseVRAM(66,29,125,39);
		}
		if(cursorx==2&cursory==3){
			Bdisp_AreaReverseVRAM(66,42,125,52);
		}
		Bdisp_PutDisp_DD();
		GetKey(&getkey);
		if(getkey==KEY_CTRL_DOWN){
			cursory++;
		}
		if(getkey==KEY_CTRL_UP){
			cursory--;
		}
		if(cursory3){
			cursory=1;
		}
		if(getkey==KEY_CTRL_RIGHT){
			cursorx++;
		}
		if(getkey==KEY_CTRL_LEFT){
			cursorx--;
		}
		if(cursorx2){
			cursorx=1;
		}
	}
	Reset_Calc();
}

I left out the global variables XD. it builds fine but just freezes XD

#24 kucalc

kucalc

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1422 posts
  • Gender:Male
  • Location:USA
  • Interests:Programming: C/C++, Fortran, LISP, COBOL 85 Standard, PHP, x86 and SH3 Assembly

    Computer graphics

  • Calculators:
    fx-9860G / fx-7400G Plus / Algebra FX 2.0+ / fx-9770G / CFX-9850G / CFX-9850GB+ / TI-89 / TI-nSpire

Posted 02 December 2007 - 04:25 PM

Sorry, but you can't use any other graphics functions except the ones provide with Revolution-FX. Also you can't use GetKey, you'll have to use IsKeyDown. GetKey will freeze the calculator.

#25 Fez

Fez

    Casio Freak

  • Members
  • PipPipPipPip
  • 162 posts
  • Gender:Male
  • Location:Australia

  • Calculators:
    Casio fx-9860G AU

Posted 03 December 2007 - 12:03 AM

Oh right XD. THanx.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users