Coding

 Closed TopicStart new topic

[WIP] CLEO 4 - Advanced Usage Guide

Deji
post Oct 21 2010, 03:40 AM
Post #1


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



WIP


CLEO 4 - Features Guide


I've made other topics around this idea, but I wanted to combine all I could find out about CLEO 4's many features and explain them. I've gone through the help file many times, but it misses out things which I have found out since. Since most opcode parameters are forwarded straight to a C-line, I went by what parameters the respective C++ functions took.


Text Formatting

In the help file, there is a topic "Форматирование текста" (text formatting) which explains how to format text. Most of the contents of this topic are a reference to the C++ functions.

If you want an English version, go here. It is specific to printf, but contains most of the relevant information. However, this mostly applies to outputting text, which can sometimes do slightly different things than when you are retrieving information. fscanf is an example (opcode 0ADA).


Much further down in the topic - a section something along the lines of "text formatting features in SCM".

This part gives info on what available features we have in SCM Coding, which of course, is much less than in C.

QUOTE
QUOTE
CLEO 4 имеет 6 опкодов для форматирования текста: 0ACE, 0ACF, 0AD0, 0AD1, 0AD2, 0AD3, 0AD3 и 0AD9.

CLEO 4 has 6 opcodes for formatting text: 0ACE, 0ACF, 0AD0, 0AD1, 0AD2, 0AD3, 0AD3 and 0AD9.


Seemingly outdated and erronous there tongue.gif So I'll correct that:

QUOTE
CLEO 4 has 9 opcodes for formatting text: 0ACE, 0ACF, 0AD0, 0AD1, 0AD3, 0AD4, 0AD9, 0ADA and 0AED.


It goes on to point out that we don't have a wide variety of data types. We only have short strings (which are useless, in my oppinion), long strings, integers and floats.


If the one at the C++ website is still too hard for you to understand, here's one that's more relevant to SCM and explains stuff a little deeper.

String Specifiers
SpecifierOutputExampleResult
a, ADisplays a float in hex form.------
cSingle non-string character or last char of a char sequence. Strings will result in a crash. Pointers work like an ordinary hex sequence."%c" 0x41A
d, iSigned decimal integer."%d, %d" 55 0xFFFFFFFF55, -1
e, EScientific notation - I have no idea what the use for such a thing is. E is exactly the same as e, but changes the case of the "e" character in the output.------
fFloat."%f" 11.511.5
g, GFloat. Uses e or f.------
nNot supported.------
oOctal (base 7 integer.. hope I got the terminology right there)."%o" 1315
pNot supported.------
sString - or pointer to a string."%s" "hi there"hi there
SNot supported.------
uUnsigned decimal number."%u, %u" 0xFFFFFFFF 5134,294,967,295, 513
x, XUnsigned hexadecimal number."%X %x" 0xABC123, 492ABC123, 1ec
%% symbol."100%%"100%



String Convention

This is specific to taking advantage of the SCM and not C. This is the thing I favour most in CLEO 4.

CLEO 4 added many new abilities when it comes to handling strings. In the help documentation, this example sticks out most:

SANNY
0ACA: show_text_box 0x859BE8


Will print out "That's a really big step".

And it is... Instead of a string we can pass any address and CLEO will read the string straight from it. Here's what you'd find at that address:

CODE
54 68 61 74 27 73 20 61 20 72 65 61 6C 6C 79 20 62 69 67 20 73 74 65 70 0A 00 00 00 0A D7 A3 3B

... which in text is...

That's a really big step
���
×£;


CLEO reads from the passed address to the end of the string (the null-terminator). If we were to use 0x859BF8, we'd output "big step".


In a nutshell, we can pass any type of string (short string, long string, short string variable or long string variable) or a pointer to any place (pointer to a variable, pointer to a label or pointer to any other address) and it will display any text characters there (anything not null).


Taking Advantage of String Convention


First, a list of opcodes that can use string convention:
0A920A940A9A (2nd param only)
0AA40AAA0AAB
0AAC0ABA0AC1
0ACA0ACB0ACC
0ACD0ACE0ACF
0AD00AD10AD3
0AD4 (input only, unfortunately)0AD70AD8
0AD90ADA (input only again)0ADB
0ADC0ADE0ADF
0AE00AE40AE5
0AE60AE7


String Pointer I/O

0AD3, 0AD7, 0ADE, 0AE6, 0AE7 and 0AED are all opcodes that can store strings in memory. This could either be memory already in the .exe or new memory, which we can create via static thread memory or dynamically allocated memory.

Thread memory is the same as in CLEO 3:

SANNY
:thread
hex
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
end


The label :thread now contains 16 blank bytes which you can use to store strings. The last byte needs to remain as a null-terminator, so you should read and write a maximum of 15 characters.

To get the address for this thread memory:

SANNY
0AC6: 0@ = label @thread offset


We can also allocate new memory.

SANNY
0AC8: 0@ = allocate_memory 16


However, I've found that for 0AC8, there is often old (probably unused) data, most likely from reallocation of memory from a game restart... So it might be useful to erase all the data like this:

SANNY
0A8C: write_memory 0@ size 16 value 0 virtual_protect 0


However, it's not always necessary. Only really necessary if you are using a method to write strings that doesn't put a trailing \0 on the end of the string... or if you just feel compulsive.


Remember, all that is stored in 0@ is an address (even for 0AC8) to a memory location. And be aware that changing the value of 0@ will loose that address from the variable, meaning you can't use it again... and you DO want to eventually use it for 0AC9, to free up memory!

This also means you can treat this address like any old integer:

SANNY
0085: 1@ = 0@


Now you'll have two pointers to the memory. One stored in 1@ and one stored in 0@, which is helpful if you want to do stuff like this:
SANNY
0A8E: 1@ = 0@ + 3
0A8C: write_memory 1@ size 1 value 0 virtual_protect 0


Now we've written 0x0 to the 3rd byte, which essentially makes the string at 0@ 2 characters long.


Now onto the good stuff.
SANNY
0AD3: 0@ = format "%d + %d = %d" 2 2 4

2 + 2 = 4 in ASCII is written to the memory.

SANNY
0AD3: 0@ = format "%X" 11

B is written to the memory.

SANNY
2@v = "my string"
0AD3: 0@ = format "%s" 2@v

my string is written to the memory.

SANNY
0AD3: 0@ = format "%c" 0x41

a is written to the memory.

More Advanced...
SANNY
2@v = "my string"
0AD3: 0@ = format "%c" 2@

s is written to the memory, because it is the last %character of 2@ (the rest is in 3@ and 4@). This specifier (%c) cannot accept strings.

SANNY
2@v = "my string"
0AD3: 0@ = format "%.7s" 2@v

my stri is written to the memory. A number after the dot specifies the length of the string.


Putting It To Use


Here's the good part and what the topics main aim to teach is.


Reading and Writing Files


There are a few problems when it comes to writing files in CLEO.

Writing Newlines

One of the first you may encounter is the lack of newline support by Sanny Builder. In most compilers, we could do things like this:

SANNY
"This is one one line.\r\nThis is on another!"


The compiler would replace \r with the hex 0xD and \n with the hex 0xA, which makes a new line in most text editors or anything that views files as plain text. Sanny Builder doesn't do this and just writes it as plain text "\r\n".

To make a new line in a file, we could either write the whole line in hex or do something like this:
SANNY
0AC8: 0@ = allocate_memory_size 42
0AD3: 0@ = format "This is on one line.%c%cThis is on another!" 0xD 0xA


Once %c is encountered, the first extra parameter will be read, which is 0xD (\r). Then on the next %c it does the same thing, get the hex character 0xA (\n) and write it.

It isn't as pretty as being able to let the compiler do it, but it's less ugly than writing it all in hex... Personally I don't mind wiriting in hex, though...


Writing/Reading Lots of Data

This problem applies for CLEO 3... but in CLEO 4 the readfile and writefile opcodes weren't modified to allow pointers. There's an easy way past this, though.

Lets say we wanna read all data from a file to an allocated memory location but we don't know how big the file is going to be...

SANNY
0A9C: 1@ = file 0@ size
0AC8: 2@ = allocate_memory_size 1@
0AC7: 3@ = var 3@ offset
0A8F: 3@ = 2@ - 3@
0016: 3@ /= 4
0A9D: readfile 0@ size 1@ to 3@(3@,1i)  // contents of the file is written to 2@
gosub @MakeSomeChange
0A9E: writefile 0@ size 1@ from 3@(3@,1i)


This post has been edited by Deji: Nov 2 2010, 03:26 PM
Reason for edit: Updated: 2nd November 2010


--------------------
Go to the top of the page
 
+Quote Post
Closed TopicStart new topic

2 User(s) are reading this topic (2 Guests and 0 Anonymous Users)
0 Members: