Development of Blake's 7 (was OASIS development)

Want to talks about games you like, would like to see developed on the Oric, it's here.
User avatar
Chema
Game master
Posts: 3019
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: OASIS very very early alpha tech demo

Post by Chema »

Hi again.

Not many advances. I did not have much free time lately, unfortunately. Anyway I did some progress, remove the C overhead and tweaked bits here and there (the engine is now less than 9.5K). Anyway I have to face design of the script interpreter and I have some doubts, so I am here asking for help.

The script language has quite a good number of commands. I am not making this compatible with any version of SCUMM, but just so you get an idea about the kind of commands here is a link: http://wiki.scummvm.org/index.php/SCUMM/V2_opcodes

First doubt: The engine provides a memory space. In old versions of scumm it is 256 16-bit words, many more in newer versions. I thought about having only 256 bytes of global storage, but now I have my doubts. I wanted to include some local storage (at least a few bytes) per thread.

Coding addresses this way means either using 8-bit pointers and considering all global storage, or keep addresses for instance from 240-255 as local storage (16 bytes per thread) and 0-239 to global storage. If more than 256 addresses are needed, then pointers should be 16-bit, which means more room for scripts.

The second doubt is about how to encode the commands. I at first thought about using specific bits for addressing modes (indicating if a parameter is a direct number or a pointer to memory space). This makes a very orthogonal instruction set.

As an example, we can have result=getDistance (objectID1, objectID2). Both parameters can be either pointers or constants.

Now, there are commands with zero, one (most), two and a few with three parameters. I cannot use 3 bits for that, because the number of different commands reduces to 32. Even using two means a total of 64 commands which is too low (I already have a list of +80).

I can simply code a completely non-orthogonal instruction set, with 1 bit indicating (for some instructions) the addressing mode of some parameter, and different codes for different addressing modes whenever this is not possible. Or simply not supporting all the addressing modes in all the instructions.

Which way should I go? Is there any sound alternative? The scumm instruction set encoding is a huge mess!

The third question is about math instructions. There are the usual addition, subtraction, multiplication and division, as well as assignment, and jumps based on comparisons (less, less or equal, greater, greater or equal, equal, not equal,...), and even logic operations. The thing is should I go to 8 or 16-bit math? At first I thought that 8-bit should be enough for a game such as this, but maybe I am missing something.

Oh, and I thought about having a table with the hi/lo bytes of the addresses of routines handling each instruction, so that the instruction number 10 is handled by the routine kept at the entry number 10. This is quite easy to manage and also fast, and is only a bad idea if there are a lot of holes in the instruction set codes. Any other suggestion?

Any input/idea/help is really appreciated!
Godzil
Squad Leader
Posts: 774
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

Re: OASIS very very early alpha tech demo

Post by Godzil »

For the instruction set, on the paper start with all the instruction you have, then for "complexe" instruction, try to figure how to do it using less complexe instruction (CISC -> RISC) you should end-up with less instruction than what you have, at the expense of a bit more larger script, but generally, complex instruction are used less time than simple one.

For memory, the more important thing for global "variable" are two state switches (so just a single bit) as it is generally used to know if the player have done something or another, I think that 240 * 8 = 1920 switches + 16 bytes would be suffisent for most of the game, and the split between switches and 8bit variable could be changed at compilation without major issue I thinkg if a game really need less switch and more variable.
You can also provide a scratch pad of 64 to 256 bytes for the current thread, this is where most of the variable will be used.


Another idea, instead of a classic memory based machine, why not making a stack machine? (like RPN or FORTH?) You will no longuer need any bit to tell the number of parameter, each instruction will just unstack the needed parameter. you will need two main instruction, pop and push, all of this could be of course masked by your script compiler, there is no need to have a stack based language, unless you directly use the corresponding assembly.

You should look how forth is implemented that could give you some ideas
User avatar
iss
Wing Commander
Posts: 1642
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: OASIS very very early alpha tech demo

Post by iss »

+1 for Godzil's idea. I was thinking about FORTH-like engine too.
User avatar
Chema
Game master
Posts: 3019
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: OASIS very very early alpha tech demo

Post by Chema »

Thanks for the input guys. It's really appreciated.

About the bit variables, I was thinking on a different approach: they share the memory space, but you will have commands to set/test individual bits. That way the programmer can use them at his convenience. The problem of having something like 256 bytes per thread is the amount of memory that it requires... For 10 threads it will mean 2.5K! But I agree that is where most vars will be used.

About the stack machine, I have toyed with that idea too, but I am not sure. The instruction could be much simpler, that is true, but the size of scripts will increase quite a lot! Something as simple as make an actor go to an object which is done with:

Code: Select all

ActorWalkToObject(actorid, objectid)
thus 3 bytes, becomes:

Code: Select all

push objectid; push actorid; ActorWalkToObject
which is 5 bytes and still needs to tell if objectid is a constant (#10) or a pointer that has to be de-referenced (var number 10).

Need to be sure before taking that direction.

I would also love to skip the need of creating a compiler, but I fear I will need to do it in the end... I was hoping that with an easy script language and macros... :(
User avatar
Dbug
Site Admin
Posts: 4459
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: OASIS very very early alpha tech demo

Post by Dbug »

So apparently SCUMM uses only one list of opcode for all the instructions - ie: "actorFollowCamera" and "isGreaterEqual" are part of the same list - ?

That's kind of weird :)

We used scripting heavily in all the games we made a Adeline Software (like Little Big Adventure and Time Commando), and in our interpreter/bytecode compiler we clearly separated instructions from functions, and we had more than enough with 256 values for each type.

For the structure itself, the code was quite simple, with each instruction using one byte, followed by the parameters it eventually needed.

In your example of ActorWalkToObject(actorid, objectid) what we would have is not three bytes, but one instruction byte followed by two expressions:

Code: Select all

instructionId=*ptr++;
switch (instructionId)
{
case ACTOR_WALK_TO_OBJECT:
	actorId =Evaluate(&ptr);
	objectid=Evaluate(&ptr);
	ActorWalkToObject(actorId,objectid);
	break;
The evaluate functions is of course dependent of the encoding, but the point is that it can perform ridiculously complicated operations such as

Code: Select all

ActorWalkToObject(myActor,GetObjectInList(Random(0,3),Box,Shoe,Book,TV));
There are many ways to encode that, and that's highly dependent on the structure of your data. You could also have specialized Evaluate functions, with optimized encoding for getting actors, objects, scripts, etc... a simple idea would be that for example you use the bit 7 to indicate if the value is immediately present (up to 128), and if not then you read one more byte that give more information, like for example the bit 7 is again used to know if it's another of the 128 other variables, else it's one of the 128 possible functions you can call and recurse.

If you room/script compiler is smart, it will know which variables are more often used and put them first, so in practice most things will still fit in one byte, and you get the possibility to get more complicated stuff at not much cost.

Code: Select all

instructionId=*ptr++;
switch (instructionId)
{
case ACTOR_WALK_TO_OBJECT:
	actorId =Evaluate(&ptr);
	objectid=Evaluate(&ptr);
	ActorWalkToObject(actorId,objectid);
	break;


U8 Evaluate(U8 **ptr)
{
	// First byte of the expression
	U8 id=*(*ptr)++;
	if (id & (1<<7))
	{
		// Get one more byte
		U8 id2=*(*ptr)++;
		if (id2 & (1<<7))
		{
			switch (id2 & 127)
			{
			case ADD:
				U8 leftVal=Evalute(ptr);
				U8 rightVal=Evalute(ptr);
				return leftVal+rightVal;

			case SUB:
				U8 leftVal=Evalute(ptr);
				U8 rightVal=Evalute(ptr);
				return leftVal-rightVal;

			case MUL:
				U8 leftVal=Evalute(ptr);
				U8 rightVal=Evalute(ptr);
				return leftVal*rightVal;

			case DIV:
				U8 leftVal=Evalute(ptr);
				U8 rightVal=Evalute(ptr);
				return leftVal/rightVal;

			case ...
			}
		}
		else
		{
			// Direct value
			return id2<<1;
		}
	}
	else
	{
		// Direct value
		return id;
	}
}
Not sure how efficient that would be on the Oric, but similar code has been running just fine for 100% of the logic of our games on PlayStation 1 and 386SX computers which were not awesomely fast machines at the time :)
User avatar
Chema
Game master
Posts: 3019
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: OASIS very very early alpha tech demo

Post by Chema »

Okay. I particularly like the idea of the expressions, as it permits some nice size optimizations. I don't know if I got the whole idea, but still need a way to indicate if a byte constant is a direct value or a variable number, whose value must be obtained. Unless there is yet another function to indicate 'content of'.

The need to use two bytes for the encoding still worries me a bit. If all parameters are 16bit then most of the problems are gone. Some of the higher Bits could be used to indicate global memory address, local memory address, constant, command,... Naturally at the expense of more room for scripts.

What if I restrict the address space to 96 16-bit global variables and another 32 for local space? Both could be accessed by word, bit or byte, depending on the instruction code (as there are 128 actions and 128 functions there could be room enough). If that sounds enough it would simplify the encoding a lot... Maybe too little room?

And what about the 8/16 bit math?

Just thinking out loud :)
User avatar
Chema
Game master
Posts: 3019
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: OASIS very very early alpha tech demo

Post by Chema »

Hi again. I have not advanced on this too much (just killed another bug and organize a few more things in the code). About the bytecode. What do you think about this idea:

- Scripts are sequences of actions (0 to 255 possible actions) with parameters. From PanCamera to If-Then-else
- Parameters can be either functions or constants. The former is indicated by bit 7 set to 1 (so 128 possible funcitons). As we need 8-bit constants, bit 6 will tell if we have a tiny 6-bit constant or we need to read the next byte to get a full 8-bit constant. This could be elaborated more if 16-bit constants are needed.

Let's imagine we have two vars: one in position 1 holding a value of 0 and another one in positions 100 holding a value of 7. The script may want to execute something such as: ActorFaceObject(*var1,GetClosestObject(*var100))

This means "Make actor stored in var 1 (that is, actor number 0) face the object which is closest to the actor stored in var 100 (that is, 7)". Let's imagine this object is number 2.

This would be coded as (GET_CONTENT gets the content of a position in memory):

Code: Select all

ACTOR_FACE_OBJECT,GET_CONTENT,1,GET_CLOSEST_OBJECT,GET_CONTENT, 01000000 (binary),100(decimal)
Action: ACTOR_FACE_OBJECT  which has 2 params
1st param:   GET_CONTENT function with one param: 
                  00000001 bit 7 is 0 (constant) bit 6 is zero (6-bit constant) so param is 1 
                  RESULT is content of address 1, that is =0 
2nd param: GET_CLOSEST_OBJECT, function with one param
                   GET_CONTENT, again function with one param
                   01000000, bit 7 is 0 (constant), bit 6 is 1, read next byte to get value 100 (decimal)
                   Result is content of address 100, that is =7
                 Result object closest to actor 7, that is =2
Result: Make Actor 0 face object 2   
And would be interpreted as expected. Is that correct? Complete?
Godzil
Squad Leader
Posts: 774
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

Re: OASIS very very early alpha tech demo

Post by Godzil »

(As I was starting to speak about OricMouse here, sorry for the short topic hijack, I've started to work on it and created a topic here: http://forum.defence-force.org/viewtopi ... 619#p13619 )
Last edited by Godzil on Thu Oct 29, 2015 6:22 pm, edited 1 time in total.
User avatar
Chema
Game master
Posts: 3019
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: OASIS very very early alpha tech demo

Post by Chema »

I noticed :) really interesting work! You hardware guys always impress me...
User avatar
Chema
Game master
Posts: 3019
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: OASIS very very early alpha tech demo

Post by Chema »

Alright, as nobody has volunteered ;) I decided to start coding the first tool I will need: a room editor. It will be an application for my usage only (so a quick and dirty hack, basically) where I could edit the image, walkboxes, and all the data needed, and to export this data in asm format ready to be included in the resource files.

Again, it will take time, but I decided to start learning some C# and .net coding along the process. The first thing I need is editing a HIRES picture on a PC, so I created a handy OricPicture class with some useful methods (get/set pixel, attributes, inverse modes, importing pic from a hires file, etc.) which is able to handle all this and render it to a bitmap object, which can be embedded, for instance, in a picturebox.

My application is, for now, able to load a hires image, and provides some basic editing functions (pixel on/off, setting attributes, zoom with grids, etc.)

Importing an image:
Captura de pantalla 2015-11-03 15.08.24.png
Zoom: notice the use of attributes and inverse mode, marked with an (Twi was mad!)
[attachment=0]Captura de pantalla 2015-11-03 17.34.21.png[/attachment]

Many many things missing, but thought you might be interested. Once fully debugged I can provide the code of the OricPicture class. But beware, as I said, that this will be an application oriented to aid in the design of OASIS rooms. Making a general application usable in other contexts by other people and in other machines/OSes is too much extra work!
Attachments
Captura de pantalla 2015-11-03 17.34.21.png
User avatar
Dbug
Site Admin
Posts: 4459
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: OASIS very very early alpha tech demo

Post by Dbug »

Chema wrote:Again, it will take time, but I decided to start learning some C# and .net coding along the process. The first thing I need is editing a HIRES picture on a PC, so I created a handy OricPicture class with some useful methods (get/set pixel, attributes, inverse modes, importing pic from a hires file, etc.) which is able to handle all this and render it to a bitmap object, which can be embedded, for instance, in a picturebox.
(...)
Making a general application usable in other contexts by other people and in other machines/OSes is too much extra work!
If it's C#, it may not be to difficult to get to run on Linux or Mac with the Mono project.
User avatar
Chema
Game master
Posts: 3019
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: OASIS very very early alpha tech demo

Post by Chema »

Well I have a first working version of the image editor. I have uploaded a video so you can have a look at how it works. Remember it is made to fit my needs in OASIS.

I have to add many other options for rooms, such as zplanes, walkbox editor, etc, as well as a "compiler" to create the resources.

But the most difficult part is done.

Here is the video:
https://youtu.be/UMhM-IsYofA

Cheers!
User avatar
ibisum
Wing Commander
Posts: 1652
Joined: Fri Apr 03, 2009 8:56 am
Location: Vienna, Austria
Contact:

Re: OASIS very very early alpha tech demo

Post by ibisum »

Looks very nice Chema! I think I learned more about AIC in the last 30 seconds than in years .. ;)
User avatar
Hialmar
Flight Lieutenant
Posts: 349
Joined: Tue Mar 04, 2014 11:25 am
Location: Toulouse, France
Contact:

Re: OASIS very very early alpha tech demo

Post by Hialmar »

Awesome by itself. Integrated with OASIS it will rock!

Where is the "like" button that I smash it ;)
Hialmar
CEO and Silicium member.
User avatar
Dbug
Site Admin
Posts: 4459
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: OASIS very very early alpha tech demo

Post by Dbug »

Post Reply