Sogna Digital Museum Forum

Sogna/VIPER Series => Research & Development => Topic started by: golden on November 03, 2010, 08:19:37 pm

Title: SOGNA's WIN Format
Post by: golden on November 03, 2010, 08:19:37 pm
The only SOGNA resource that isn't completely reversed is the WIN format. It's an opcode-based script that defines every action within the Viper games. The main algorithm that performs the interaction between the SGS.EXE and a *.WIN file can be written in pseudo-code as:

Code: [Select]
open WIN file
while( end-of-file isn't reached )
{
   opcode = read 1 byte
   switch( opcode )
   {
      case 0x00: do nothing
      case 0x01: read 2 bytes; read 2 bytes; do some stuff
      ...
      case 0x03: read 1 byte; read filename; do some stuff
      ...
   }
}
close WIN file

Viper V6's SGS.EXE defines 75 different opcodes (0x4B) and the following information describes what JG00, 黒い灯影 and I have found about them:

Code: [Select]
[]     - 1 Byte
[[]]   - 2 Bytes
[[[]]] - 4 Bytes
{}     - Variable Length

XX  - Unknown
??  - Unknown
(?) - Partially Known or Need to be confirmed


VIPER V6
========

[01][[Left]][[Top]] - Set Viewport Position

     Stores Top @ 427570
     Stores Left @ 427574


[02][[Width]][[Height]] - Set Viewport Size


[03][Slot]{FileName}[00] - Load ANM

     Load ANM file and associate with Image Slot.


[04][XX] - ??

(continues below)
Title: Re: SOGNA's WIN Format
Post by: golden on November 03, 2010, 08:24:53 pm
Code: [Select]
[05][Color][[Frames]] - Fade In

     Fade in from Color (00=Black, FF=White). Frames is number of frame refreshes (0001: Fast, FFFF: Slow).


[06][Color][[Frames]] - Fade Out

     Fade out to Color (00=Black, FF=White). Frames is number of frame refreshes (0001: Fast, FFFF: Slow).


[07][Slot] - Set Viewport Palette


[08] - WaitForSingleObject (?)

     Stores 1 @ 420550
     Stores 0 @ 420564
     Stores 0 @ 42055C
     Stores 5 @ 420580


[09] - WaitForSingleObject (?)

     Stores 0 @ 420550
     Stores 0 @ 420564
     Stores 0 @ 42055C
     Stores 5 @ 420580


[0A][Slot][[Left]][[Top]][R?][G?][B?][[Colors]][[Frame]] - Display ANM (?)

     Prints ANM's Frame @ XPos & YPos
     Stores YPos @ 427570
     Stores XPos @ 427574


[0B][XX] - ??


[0C][XX] - ??


[0D] - ??


[0E] - ??

     Relation to [15]?


[10][XX] - ??


[12][XX][XX][XX][[XXXX]][[XXXX]] - ??


[13][[Time]] - Sleep

     Sleep for the specified number of hundredth-seconds (a value of 100 sleeps for one second).


[14][[Offset]] - Jump

     Unconditionally Jumps to StartOfWIN+Offset


[15][[Offset]] - Conditional Jump

     Stores StartOfWIN+Offset @ 420570
     If Mouse Button is pressed, Jumps to StartOfWIN+Offset
     Relation with [0E] and [3E]?


[17][XX][[XXXX]][[XXXX]][[XXXX]][[XXXX]][[XXXX]][[XXXX]][[XXXX]] - ??


[19][Loop][Slot] - Play MIDI

     Play MIDI in specified Audio Slot. If Loop is nonzero, it should loop; if zero, it will play just once.


[1A] - Stop MIDI


[1B][Slot]{FileName}[00] - Load MIDI

     Load specified MIDI file to Audio Slot. Slot generally begins at 2 because the audio streams are shared between MIDI and PCM. Slots 0 and 1 would generally be used by voice and sound effects.


[1D][Slot]{FileName}[00] - Play PCM

     Slot should be 0 or 1, see [1B].


[1E] - Stop PCM


[1F] - ??

     Must use after [28]?


[20][[Left]][[Top]][Chars][Lines] - Text Box Display

     Chars is number of half-width characters (54 means 27 full width chars can be shown) - this number should probably always be a multiple of two for this reason.


[21]{String}[00] - Display String

     Displays Shift-JIS encoded String. Some characters direct the program to perform special actions: full-width dollar sign (Unicode FF04) translates to a half-width space (Unicode 20); full-width caret character (Unicode FF3E) causes the entire active text box to be cleared; a full-width Yen symbol (FFE5) causes a new line; 01XX causes token replacement using token XX minus 1 (see [24]).


[22][Mode] - Set Wait Mode (?)

     Stores Mode @ 4204DC


[23][Height] - Create Font

     Width = Height/2
     CreateFontA @ 414A0E
     By default, creates a MS Gothic True-Type font.


[24][Token]{String}[00] - Store String

     Associates a text token with a token number. This is used primarily for names and String can include characters that get translated in [21].


[25][[Offset]] - Jump (?)

     Loads Index stored @ 42056C
     Stores next opcode offset (after this [25][[Offset]]) @ Index*4+4275A8
     Increments Index @ 42056C


[28][Effect][[Speed]][Colors]{Palette} - Display ANM (?)

     Effect: 0 - No effect, 1 - FadeOut, 2 - FadeOut & FadeIn repeatedly
     Palette: (Colors * 3 + Colors) bytes
     It's used to display the gray viper logo!


[29][[Offset]] - Enable Menu Item (?)

     Enables Item 0x75 ('Exit Menu'), Menu NULL
     Stores StartOfWin+Offset @ 420578


[2A] - Disable Menu Item (?)

     Disables Item 0x75 ('Exit Menu'), Menu NULL
     Stores 0x00 @ 420578


[2B][[Offset]] - Enable Menu Item (?)

     Enables Item 0x00, Menu 0x02E40BDD
     Stores StartOfWIN+Offset @ 42057C (Is this how it saves the game??)


[2C] - Disable Menu Item (?)

     Disables Item 0x00, Menu NULL


[2D] - Reset Jump Offset (?)

     Sets Addresses 420570 & 420574 to 0
     Related to [15]?


[2E][Index][[ConditionA]][[Offset]] - Conditional Jump

     Loads ConditionB stored @ Index*2+426E3C
     Checks if ConditionA == ConditionB and if so, Jumps to StartOfWIN+Offset


[2F][Index][[ConditionA]][[Offset]] - Conditional Jump

     Loads ConditionB stored @ Index*2+426E3C
     Checks if ConditionA != ConditionB and if so, Jumps to StartOfWIN+Offset


[30][Index][[ConditionA]][[Offset]] - Conditional Jump

     Loads ConditionB stored @ Index*2+426E3C
     Checks if ConditionA >= ConditionB and if so, Jumps to StartOfWIN+Offset


[31][Index][[ConditionA]][[Offset]] - Conditional Jump

     Loads ConditionB stored @ Index*2+426E3C
     Checks if ConditionA <= ConditionB and if so, Jumps to StartOfWIN+Offset


[32][Index] - Store Jump Condition for [33] & [48]

     Loads Condition stored @ Index*2+426E3C
     Stores Condition @ 42703C


[33][[ConditionA]][[Offset]] - Conditional Jump

     Loads ConditionB stored @ 42703C
     Checks if ConditionA != ConditionB and if so, Jumps to StartOfWIN+Offset


[34][Index][[Condition]] - Store Jump Condition for [32]

     Stores Condition @ Index*2+426E3C


[35][XX] - ??


[38][Index][[Condition]] - Store Jump Condition for [32]

     ORs Condition with content stored @ Index*2+426E3C


[3B] - Create Registry Key

     Calls RegCreateKeyEx(SubKey = ".Default\Software\SOGNA\V6", hKey = HKEY_USERS)


[3D][[Left]][[Top]][[Width]][[Height]] - Paint Black Rectangle

     ROP = 42 (BLACKNESS) @ 4150E0: PatBlt


[3E][00][[XXXX]][[XXXX]][XX][Lines]{String}[00] - Display String (?)


[40][Condition] - Enable or Disable Menu Item (?)

     If Condition == 0: Disables Item 0x01, Menu 0x001108C5
     If Condition != 0: Enables Item 0x01, Menu 0x001108C5


[41][Colors]{Palette} - Display ANM (?)

     Must use after [28][...][1F]?


[43][[XXXX]] - ??

     Stores XXXX @ 4204E8


[45][Index] - ??

     Loads XX stored @ 42054C
     Stores XX @ Index*2+426E3C


[46] - ??

     Loads Condition stored @ 42054C
     Checks if Condition != 0 and if so, Stores 0x0B @ 420580


[48][[ConditionA]][[Offset]] - Conditional Jump

     Loads ConditionB stored @ 42703C
     Checks if ConditionA AND ConditionB == 0 and if so, Jumps to StartOfWIN+Offset


[4A]{FileName}[00] - Load WIN


[4B][[Left]][[Top]] - Set Caret

     Specifies the location of the wait caret (the animated keypress icon in the lower right of the text box)

As you can see, there are a few opcodes that directly influence which RAM addresses the game accesses. Others, such as 0x08 or 0x09, are used to maintain thread synchronicity by calling the WINAPI function 'WaitForSingleObject' and I'm not sure when they're supposed to be used. So it's not just a matter of knowing what the opcodes do but also when they can be used and what other opcodes they influence.

I should also say that this information was obtained mainly by observing MAIN.WIN and START.WIN, I didn't investigate the other files much because I had already discovered all relevant opcodes necessary to produce an English translation.

One method that's been particularly helpful in investigating the opcodes is using Hex Workshop and its bookmark feature to produce this nice visual aid:

(http://imgur.com/o0hV7.png)

The bookmarks are specific to each file and I only made one for START.WIN (http://dl.dropbox.com/u/2910075/startwin.hbk) and another for MAIN.WIN (http://dl.dropbox.com/u/2910075/mainwin.hbk). If someone wants to try this method just go to 'Tools -> Bookmarks -> Open Bookmark Collection...' in Hex Workshop and select the respective bookmark file.
Title: Re: SOGNA's WIN Format
Post by: JG on November 04, 2010, 10:45:52 pm
Fantastic stuff.

I can shed some light on the WaitForSingleObject code though.  It's needed to wait for user input.  If the system wasn't multithreaded it wouldn't allow you to access the menu or record your keypresses while it was in the middle of drawing a scene, at least not without polling.  Thus, the drawing is in one thread and user input is in another.  Sound and speech may be in one or the other or its own thread altogether (but considering theres only two wait states available, I'm assuming its tied to the drawing thread).  One of the wait states (the more common of the two) would be used by the drawing thread to wait for user input thread (waiting for mouseclick to continue) and the other one (the less frequently used one) used by user input thread to wait for drawing thread to finish (usually during a scrolling action like when Carrera first appears)
Title: Re: SOGNA's WIN Format
Post by: JG on November 05, 2010, 08:02:55 pm
Clarifications I'm discovering as I write my decompiler:

Code: [Select]
[20][[left]][[top]][chars][lines]

Left and top are client area coordinates of text box.  Chars is number of half-width characters (54 means 27 full width chars can be shown) - this number should probably always be a multiple of two for this reason.  Lines is obvious.  This opcode essentially draws a blank rectangle sufficiently large enough to draw over any text written previously in that area.

Code: [Select]
[22][charwidth] - set font width

I beleive the 22 02 that follows tells the system that the font is double-wide.  For your English conversion, you may want to try 22 01 here.

Code: [Select]
[4B][[left]][[top]] - Set caret position

This specifies the location of the wait caret (the animated keypress icon in the lower right of the text box)

Code: [Select]
[03][slot]{FileName}[00] - Load ANM to slot
[07][slot] - Set viewport palette from image loaded in slot
[0A][slot][[left]][[top]][R?][G?][B?][[Colors]][[Frame]] - Display ANM

The second byte in these opcodes identify a slot, much like opcode 1B does for MIDIs.  I presume audio slots and ANM slots are distinct and not shared (otherwise loading WINDOW.ANM to slot 3 would destroy a loaded MIDI)

Your original understanding of 0A seems to be way off.  I'm pretty sure the last two bytes are frame number (not just one byte followed by 00), and the two bytes previous to that is the number of colors in the file (usually 256).  This leaves three colors in the middle, which have almost got to be related to transparent color.  I'm not sure yet in which order the red, green, and blue components are ordered though.
Title: Re: SOGNA's WIN Format
Post by: 黒い灯影 on November 06, 2010, 01:12:26 am
OPCODE 15 is an IF statement..i think, different from OPCODE 14
I found out it doesn't jump, unless you click on the mouse...
Title: Re: SOGNA's WIN Format
Post by: golden on November 06, 2010, 07:49:29 am
I can shed some light on the WaitForSingleObject code though.  It's needed to wait for user input.  If the system wasn't multithreaded it wouldn't allow you to access the menu or record your keypresses while it was in the middle of drawing a scene, at least not without polling.  Thus, the drawing is in one thread and user input is in another.

Ah, that explains a lot. Thanks JG00, your expertise with the WINAPI will come in handy.

Clarifications I'm discovering as I write my decompiler:

Excellent work JG00. And yeah, your version of 0A makes much more sense, it was one of the first opcodes I was investigating and I really wasn't thorough enough. I'm going to merge your findings into my original post for consistency.

OPCODE 15 is an IF statement..i think, different from OPCODE 14
I found out it doesn't jump, unless you click on the mouse...

Ah, so that's what it's doing. The only difference between 14 and 15 is that 14 immediately sets the file pointer to the resulting offset while 15 just stores it at 0x420570. I wasn't sure why it was doing that since I had verified that it was a jump opcode.

黒い灯影, do you think it's safe to assume that 15 is the opcode that defines the action of skipping the intro (SOGNA screen and Viper logo) to the story selection menu, for example?


EDIT: Just found out that [1E] stops a playing PCM and that [19] plays a MIDI. Also, [1A] stops a playing MIDI. List updated.

EDIT2: A lot of these opcodes seem to be doing thread-related work behind the scenes, I see [08], [09], [0B], [0C], [0D], [43] calling 'WaitForSingleObject' and 'ReleaseMutex'. They're doing other stuff in-between but for now they should probably be saved for last..
Title: Re: SOGNA's WIN Format
Post by: JG on November 07, 2010, 02:58:57 pm
Here's my notes thus far.  I'm able to decompile about 80% of the V6 WIN instructions so far.  I'm also listing the ones that are confirmed first, and the ones that are guesses or not as sure about underneath to clearly deliniate what is "known" vs what is not.

Some of this clarifies your questions about certain opcodes (like 15)


Confirmed:

00
Stop command (usually only shows up at end of file)

01 left_low left_high top_low top_high
Set viewport position (in pixels)

02 width_low width_high height_low height_high
Set viewport size (in pixels)

03 slot {filename} 00
Load ANM file and associate with image slot. Filename is terminated by null character and does not require .ANM extension.

05 color frames_low frames_high
Fade in from color (00=black, FF=white). Frames is number of frame refreshes (at 30 per second?) it takes to completely fade in.

06 color frames_low frames_high
Fade out to color (00=black, FF=white). Frames is number of frame refreshes (at 30 per second?) it takes to completely fade out.

07 slot
Set viewport palette to match ANM file associated with specified slot (This is a Windows GDI requirement for 8 bit graphics. It doesn't have much use in today's world.)

0C slot
Render ANM file in specified slot.  Always seems to follow 0A.

0E
Wait for hotzone selection.

13 hundredth_of_seconds_low hundredth_of_seconds_high
Sleep for the specified number of hundredth-seconds. (A value of 100 sleeps for one second.)

14 pointer_low pointer_high
Jump to specific pointer.

15 pointer_low pointer_high
Jump on hotzone selection. I beleive value register 0 holds FFFF until input is made.  If no input is made a following opcode 14 usually jumps back up and checks 15 again until input is made. (I know what the opcode does, just not how the register values are set to influence it.)

19 loop slot
Play MIDI in specified audio slot. If loop is nonzero, it should loop; if zero, it will play just once.  Only one MIDI can play at once.

1A
Stop playing MIDI file.  Since only one can be playing at a time, there is not slot to specify.

1B slot {filename} 00
Load specified MIDI file to audio slot (but don't play.) Slots generally begin at 2 becuase the audio streams are shared between MIDI and PCM. Slots 0 and 1 would generally be used by voice and sound effects. Filename is terminated by null character and does not require .MID extension.

1D slot {filename} 00
Immediately play specified PCM file to audio slot. Slot should be 0 or 1. Filename is terminated by null character and does not require .PCM extension.

1E
Stop playing PCM file. Since only one can be playing at a time, there is not slot to specify.

20 left_low left_high top_low top_high char_columns lines
Set active text area. Position and top are in pixels. Char_columns is number of half-width character-wide columns to allocate (since most of VIPER uses kanji, this number is usually twice as large as the number of kanji characters to be displayed. Line is number of lines of text tall.  Thus, the actual size of the text area is dependant entirely on font size (see opcode 23.) The active text area can be redefined without destroying the text already displayed to screen (used to great effect in the P-Warrior Corner to show three different font sizes on the VIPER-BTR introduction screen.)

21 {shift_jis_text} 00
Display shift-JIS encoded text, terminated by null character. Some characters direct the program to perform special actions: Full-width dollar sign (Unicode FF04) translates to a half-width space (Unicode 20), Full width caret character (Unicode FF3E) causes the entire active text box to be cleared; a full-width Yen symbol (FFE5) causes a new line; and the 01XX causes token replacement, using token XX minus 1 (see opcode 24.)

22 mode
Set wait mode. Not sure what the mode values are yet but one value indicates that use can click to continue and the other disables the ability.

23 font_size
Set font size. SGS.EXE has an embedded MS Gothic True-Type font.

24 token {shift_jis_text} 00
Associates a text token with a token number. This is used primarily for names. Text is terminated by a null character and can include characters that get translated in opcode 21.

32 register
Read value register value into comparison register.

33 value_low value_high pointer_low pointer_high
Conditional jump to pointer location on equality (or nonequality?) to value in comparison register.

34 register value_low value_high
Write value to specified value register.

3B
Create registry tree (if needed)

3D left_low left_high top_low top_high width_low width_high height_low height_high
Blacks out the specified rectangle. (Might also be used to specify the window region - someone should try this with different numbers and see if either the window or client area changes size.)

3E left_low left_high top_low top_high char_columns lines {(text 00)}
Displays hot text at the specified location. The clicking of each line stores a different value to value register 0, which impacts how opcode 15 operates (though I haven't mapped out exactly how yet.) Each line of text is itself terminated by a null character, but there is no additional null character after the last line.

4A {filename} 00
Transfers control to specified WIN file. Filename is terminated by null character and does not require the .WIN extension.

4B left_low left_high top_low top_high
Set waiting caret graphic position to specified coordinates.




Unconfirmed:

04 byte1 byte2 byte3 byte4 byte5
Set checkpoint? Not sure what bytes correspond to.

09
Flush/Commit drawing operations?  Seems to always follow a series of drawing operations.

0A slot left_low left_high top_low top_high byte1 byte2 byte3 byte4 byte5 byte6 {extra bytes} 00
Set ANM properties for specified image slot. Left and Top positions are confirmed.  Then theres at least 6 bytes whose purpose isn't yet known.  Then theres a series of additional bytes until a zero byte is encountered.  These must indicate the order and timing of frames to display but I haven't yet bothered to investigate.

10 byte1 byte2 byte3 byte4
Not sure what it does but it's always followed by four bytes

17 word1_low word1_high word2_low word2_high word3_low word3_high byte4 byte5
Something to do with scrolling actions. Always followed by 8 bytes (organized into three wrods and 2 extra bytes I think.) The words might be starting location or how many pixels to scroll on each cycle. One of the bytes has to indicate direction (up, down, left, right, or a diagonal) - need more examples to figure this out.

25 pointer_low pointer_high
Wait for input?  THis is definately some kind of jump if some condition is met (perhaps a special debug condition?)

28 byte1 word2 colors {(palatte_index red green blue)} byte3 byte4 colors {(palatte_index red green blue)}
Perform some kind of palette replacement on an ANM file. Not sure what some of the bytes mean. The word may be the number of cycles it takes before switching back. The two colors bytes indicate number of colors in the arrays.  Each arra is a platte index, followed by 3 bytes for color (unsure if component ordering is red-green-blue or something else)

2B byte1 byte2 byte3
Unknown. Possibly text to hot zone related. Always seems be followed by three bytes whose function is unknown.

2D word1_low word1_high word2_low word2_high
Either resets some kind of coordinates, possibly for where to write hotzone text, or does something else with a single word value, and word2 is standard opcodes.  Need to see more examples of this opcode in action to be sure.


2E byte1 byte2 byte3 byte4 byte5
Unknown. Possibly text to hot zone related. Always seems be followed by five bytes whose function is unknown; the last four bytes may be organized as two words instead.

35 byte1 byte2 pointer_low pointer_high
Another kind of conditional jump, similar to opcode 33.  Not sure what the bytes do, and they are usually equal in value.  Perhaps its a "is comparison register value between byte1 and byte2" comparison.

42
I think it disables input until after the next ANM is drawn.  This shows up in The Devil Came...'s game over screen, to disallow input skipping between Carrera's angry voice, the lightning bolt sound, and the text display of Ogawa's "Wah!!" death throes sound.

43 word_low word_high
I beleive this sets the text per-character delay.

48 word1_low word1_high word2_low word2_high
Unknown.  Always followed by four bytes, probably organized into two words.
Title: Re: SOGNA's WIN Format
Post by: golden on November 07, 2010, 05:23:23 pm
Great, you've confirmed some nice stuff! I've updated my list with your findings and also marked the ones I'm not sure with (?) and the ones that are completely unknown with ??. I've also got a few comments/questions and I should clarify some of my findings:


I forgot to mention that I'm completely sure about opcode sizes because I'm using a debugger and I have a breakpoint at the ASM instruction responsible for reading each opcode so I can see how many bytes it skips when moving to the next one. You should check my list to confirm opcode sizes, for instance, the [04] opcode only reads 1 byte and not the 5 you've mentioned. [10] and [35] also read 1 byte only.


EDIT: By the way, we should be using some sort of collaborative tool like Google Docs, I can set up a public document (modifiable by the three of us) with what we already have. What do you think?
Title: Re: SOGNA's WIN Format
Post by: JG on November 07, 2010, 08:18:17 pm
Regarding [0C], it seems to be the case but it doesn't follow the [0A] associated with HEBI.ANM in START.WIN. HEBI has 2 frames, could it be related?
I suspect opcode 28 duplicates the rendering functionality of 0C.

I've already documented [32], [33] and [34].
Your wording is needlessly complicated though.  The way I see it SGS defines 257 registers.  256 for values and one for comparison.  Where the register values are stored should be arbitary, and may not be the same address in later versions of SGS.

I've also confirmed [1E], it's a single byte opcode.
Correct.  I have updated my list.

[25] is a jump opcode like [14] but it does some stuff in-between which I haven't confirmed yet; check my notes.
Yes. You are correct that its a jump operation of some kind. I was thrown off by the second byte value (which is how I arrived at opcode 4E by mistake)
However, this opcode occurs between text that is displayed, so it's got to be used to turn on the wait state.

I haven't confirmed [2B] yet but it calls WINAPI functions 'EnableMenuItem' and 'DrawMenuBar'.
That helps a little. But unless we can figure out what the bytes that follow 2B means, we won't know exactly how this controls the menu. I presume one or two bytes have to tell us which menu item, and another byte tells us enable or disable. (unless 2C also calls EnableMenuItem but set the enable flag to false instead)

Title: Re: SOGNA's WIN Format
Post by: JG on November 07, 2010, 08:19:17 pm
Also haven't confirmed [2D] but it seems to reset the jump offset from [15].
I've documented [2E] and [48], they're conditional jumps.
I need to see more occurances of these opcodes to be sure of their function.

The opcode table only has 0x4B opcodes so there is no [4E] or [FF].
Yeah, my decompiler isn't 100% yet and was producing these opcodes in error.

I forgot to mention that I'm completely sure about opcode sizes because I'm using a debugger and I have a breakpoint at the ASM instruction responsible for reading each opcode so I can see how many bytes it skips when moving to the next one. You should check my list to confirm opcode sizes, for instance, the [04] opcode only reads 1 byte and not the 5 you've mentioned. [10] and [35] also read 1 byte only.
Can you supply the lengths of all the opcodes for me? I'm decoding as I go so I have to figure out how many bytes are being consumed by trial and error. (I realize 0A, 28, and any opcode dealing with text are variable in length.)

EDIT: By the way, we should be using some sort of collaborative tool like Google Docs, I can set up a public document (modifiable by the three of us) with what we already have. What do you think?
I'm not sure we need to go until that much work. With a few more days I think we can get a working disassembler going and then such information will no longer be needed.


Sorry - I had to split this into two posts.  Seems PHP couldn't parse the entire post without raising a server error.
Title: Re: SOGNA's WIN Format
Post by: golden on November 07, 2010, 08:50:10 pm
Your wording is needlessly complicated though.  The way I see it SGS defines 257 registers.  256 for values and one for comparison.  Where the register values are stored should be arbitary, and may not be the same address in later versions of SGS.
I totally agree, I'm just keeping those addresses because many of them are hardcoded into the program and shared between opcodes so it's easier to discover which opcodes are related to each other - that's how I found that [32] was related to [33] and [48] for example. And how [2D] is probably related to [15].

Can you supply the lengths of all the opcodes for me? I'm decoding as I go so I have to figure out how many bytes are being consumed by trial and error. (I realize 0A, 28, and any opcode dealing with text are variable in length.)
They are already on my list. If you don't like my 'bracket syntax', we can agree on a different one, I just wanted a less verbose way to describe the opcodes' sizes and their arguments.


EDIT: I found some more info regarding [04], the next byte seems to act as a flag; if set to 1 then the program enters a loop where a sequence of functions 'GlobalHandle', 'GlobalUnlock' and 'GlobalFree' are called. After the loop, the program executes another sequence of the same functions mentioned above. If the flag is set to 0, the only difference is that the program skips the loop. I didn't see any visual differences whether this opcode is omitted or not, though.

EDIT2: I just found that [04] and [10] are related. [10] is executed the moment the game enters the story selection screen and [04] is executed when I click one of the 4 possible options at that screen. [10] executes 'GlobalAlloc' with MemSize=0x384 and Flags=GMEM_MOVEABLE (these parameters are invariable btw); then it immediately executes 'GlobalLock' for the address returned by the previous function.

I noticed that [04] performs those sequences of functions for the addresses on which [10] performed the allocs/locks. The following byte seems to influence which address gets selected to store the address used for the memory allocation.

(continues below)
Title: Re: SOGNA's WIN Format
Post by: golden on November 08, 2010, 01:03:41 pm
So now I think that the flag byte from [04] isn't a flag but also influences which address gets selected for deletion. I hope you can shed some light on this new info JG00.

(also had to make a new post due to a server error)
Title: Re: SOGNA's WIN Format
Post by: JG on November 08, 2010, 07:27:37 pm
I found some more info regarding [04], the next byte seems to act as a flag; if set to 1 then the program enters a loop where a sequence of functions 'GlobalHandle', 'GlobalUnlock' and 'GlobalFree' are called.

...

[10] is executed the moment the game enters the story selection screen and [04] is executed when I click one of the 4 possible options at that screen. [10] executes 'GlobalAlloc' with MemSize=0x384 and Flags=GMEM_MOVEABLE (these parameters are invariable btw); then it immediately executes 'GlobalLock' for the address returned by the previous function.

Ok, so its allocated 900 bytes of shared memory that only a single thread can operate on at once.  So its obviously got something to do with the multithreading, I just wish it was more obvious what exactly. Might be doing something to capture the mouse click coordinates and convert to which hot image is selected.
Title: Re: SOGNA's WIN Format
Post by: JG on November 09, 2010, 08:34:36 pm
Do you think you could whip up a WIN file with some of the following codes and run them through your debugger to figure out ...
1) How many bytes these codes consume - needed to get my decompiler working reliably
2) What API calls are made, if any - with this I can help determine what these opcodes do
3) What bit operations (And, Not, Or, Xor) they make - I suspect 47 or 49 is like 48, but uses Or or Xor instead. In fact, if you can get assembler code instructions out of your debugger for what happens in these opcodes, that might be even better.

0D
0F
10
11
12
18
1C
1F
26
27
2D
2F
30
31
35
36
37
39
3A
3F
43
44
46
47
49
Title: Re: SOGNA's WIN Format
Post by: JG on November 09, 2010, 10:11:12 pm
Some new info I've confirmed:

[28][effect][[cycles]][colors]{palette}
Modifies palette with an effect over time. The palette size is 4*colors and is ordered [palette index][[[rgb]]]

[41][colors]{palette}
Modifies palette right now. The palette size is 4*colors and is ordered [palette index][[[rgb]]]

[2E][register][[value]][[to]]
Jump if specified register equals value (or does not equal value?)
Doing opcode 32 (read) followed by some 33s (jump_if_not_equals) does the same thing but 2E seems to be a shortcut.  (2D or 2F may be the reverse logic of this operation.)

[17][direction?][[start_x]][[end_x]][[width]][[stary_y]][[end_y]][[height]][cycles]]
Scrolls the viewport form start coordinates to end coordinates over time.  Not sure why width and height need to specified (opcode 02 should have already done that).  Not entirely sure the first argument byte is direction but it seems reasonable (I need to see some more examples of this opcode in action to be sure.)

[35][register]
Increment register. (I wonder if 36 is a decrement?)


And partially confirmed some more about

[0A][image][[left_x]][[top_y]][?][?][?][?]{frames}
Not yet sure what the four bytes in the middle mean yet but I've solved the frames.  They are ordered in pairs of bytes, until the first byte in a pair is zero.  The first byte is the frame index, and the second byte is how many cycles its displayed before the next pair is processed.
Title: Re: SOGNA's WIN Format
Post by: golden on November 13, 2010, 03:36:49 pm
Sorry for taking so long to reply, been really busy these past few days.

In fact, if you can get assembler code instructions out of your debugger for what happens in these opcodes, that might be even better.

Sure, here they are:

[0D]
Code: [Select]
004144F1  |> 68 E8030000    |PUSH 3E8                                ; /Timeout = 1000. ms; Case D of switch 00413F2B
004144F6  |. FF35 D0754200  |PUSH DWORD PTR DS:[4275D0]              ; |hObject = NULL
004144FC  |. E8 D6480000    |CALL <JMP.&KERNEL32.WaitForSingleObject>; \WaitForSingleObject
00414501  |. 85C0           |TEST EAX,EAX
00414503  |. 74 0A          |JE SHORT SGS_NOCD.0041450F
00414505  |. E8 800F0000    |CALL SGS_NOCD.0041548A
0041450A  |. E9 670F0000    |JMP SGS_NOCD.00415476
0041450F  |> 33C9           |XOR ECX,ECX
00414511  |> 69C1 88000000  |/IMUL EAX,ECX,88
00414517  |. 33D2           ||XOR EDX,EDX
00414519  |. 8914C5 3434420>||MOV DWORD PTR DS:[EAX*8+423434],EDX
00414520  |. 41             ||INC ECX
00414521  |. 83F9 08        ||CMP ECX,8
00414524  |.^7C EB          |\JL SHORT SGS_NOCD.00414511
00414526  |. C705 80054200 >|MOV DWORD PTR DS:[420580],5
00414530  |. FF35 D0754200  |PUSH DWORD PTR DS:[4275D0]              ; /hMutex = NULL
00414536  |. E8 60480000    |CALL <JMP.&KERNEL32.ReleaseMutex>       ; \ReleaseMutex
0041453B  |. E9 360F0000    |JMP SGS_NOCD.00415476

[0F]
Code: [Select]
00414557  |> 6A 01          |PUSH 1                                  ; /Arg1 = 00000001; Case F of switch 00413F2B
00414559  |. E8 42E8FFFF    |CALL SGS_NOCD.00412DA0                  ; \SGS_NOCD.00412DA0
0041455E  |. 59             |POP ECX
0041455F  |. C705 80054200 >|MOV DWORD PTR DS:[420580],1
00414569  |. E9 080F0000    |JMP SGS_NOCD.00415476

[10][XX]
Code: [Select]
0041456E  |> 8B06           |MOV EAX,DWORD PTR DS:[ESI]              ;  Case 10 of switch 00413F2B
00414570  |. FF06           |INC DWORD PTR DS:[ESI]
00414572  |. 0FB600         |MOVZX EAX,BYTE PTR DS:[EAX]
00414575  |. 50             |PUSH EAX                                ; /Arg1
00414576  |. E8 78D6FFFF    |CALL SGS_NOCD.00411BF3                  ; \SGS_NOCD.00411BF3
0041457B  |. 59             |POP ECX
0041457C  |. E9 F50E0000    |JMP SGS_NOCD.00415476

[11]
There is no opcode [11].

[12][XX][XX][XX][[XXXX]][[XXXX]]
Code: [Select]
00414581  |> 8B06           |MOV EAX,DWORD PTR DS:[ESI]              ;  Case 12 of switch 00413F2B
00414583  |. 0FB600         |MOVZX EAX,BYTE PTR DS:[EAX]
00414586  |. 8945 F8        |MOV DWORD PTR SS:[EBP-8],EAX
00414589  |. FF06           |INC DWORD PTR DS:[ESI]
0041458B  |. 8B06           |MOV EAX,DWORD PTR DS:[ESI]
0041458D  |. 0FB638         |MOVZX EDI,BYTE PTR DS:[EAX]
00414590  |. FF06           |INC DWORD PTR DS:[ESI]
00414592  |. 8B06           |MOV EAX,DWORD PTR DS:[ESI]
00414594  |. 0FB600         |MOVZX EAX,BYTE PTR DS:[EAX]
00414597  |. 8945 F4        |MOV DWORD PTR SS:[EBP-C],EAX
0041459A  |. FF06           |INC DWORD PTR DS:[ESI]
0041459C  |. 8B06           |MOV EAX,DWORD PTR DS:[ESI]
0041459E  |. 0FB718         |MOVZX EBX,WORD PTR DS:[EAX]
004145A1  |. 8306 02        |ADD DWORD PTR DS:[ESI],2
004145A4  |. 8B06           |MOV EAX,DWORD PTR DS:[ESI]
004145A6  |. 0FB700         |MOVZX EAX,WORD PTR DS:[EAX]
004145A9  |. 8945 F0        |MOV DWORD PTR SS:[EBP-10],EAX
004145AC  |. 8306 02        |ADD DWORD PTR DS:[ESI],2
004145AF  |. FF75 F0        |PUSH DWORD PTR SS:[EBP-10]              ; /Arg5
004145B2  |. 53             |PUSH EBX                                ; |Arg4
004145B3  |. FF75 F4        |PUSH DWORD PTR SS:[EBP-C]               ; |Arg3
004145B6  |. 57             |PUSH EDI                                ; |Arg2
004145B7  |. FF75 F8        |PUSH DWORD PTR SS:[EBP-8]               ; |Arg1
004145BA  |. E8 69D6FFFF    |CALL SGS_NOCD.00411C28                  ; \SGS_NOCD.00411C28
004145BF  |. 83C4 14        |ADD ESP,14
004145C2  |. E9 AF0E0000    |JMP SGS_NOCD.00415476

[18][XX]
Code: [Select]
004147AB  |> 8B06           |MOV EAX,DWORD PTR DS:[ESI]              ;  Case 18 of switch 00413F2B
004147AD  |. 8A18           |MOV BL,BYTE PTR DS:[EAX]
004147AF  |. FF06           |INC DWORD PTR DS:[ESI]
004147B1  |. 68 E8030000    |PUSH 3E8                                ; /Timeout = 1000. ms
004147B6  |. FF35 D0754200  |PUSH DWORD PTR DS:[4275D0]              ; |hObject = NULL
004147BC  |. E8 16460000    |CALL <JMP.&KERNEL32.WaitForSingleObject>; \WaitForSingleObject
004147C1  |. 85C0           |TEST EAX,EAX
004147C3  |. 74 0A          |JE SHORT SGS_NOCD.004147CF
004147C5  |. E8 C00C0000    |CALL SGS_NOCD.0041548A
004147CA  |. E9 A70C0000    |JMP SGS_NOCD.00415476
004147CF  |> 33C0           |XOR EAX,EAX
004147D1  |. 8AC3           |MOV AL,BL
004147D3  |. 69C0 88000000  |IMUL EAX,EAX,88
004147D9  |. F604C5 3534420>|TEST BYTE PTR DS:[EAX*8+423435],80
004147E1  |. 74 27          |JE SHORT SGS_NOCD.0041480A
004147E3  |. 33C0           |XOR EAX,EAX
004147E5  |. 8AC3           |MOV AL,BL
004147E7  |. 69C0 88000000  |IMUL EAX,EAX,88
004147ED  |. F604C5 3434420>|TEST BYTE PTR DS:[EAX*8+423434],10
004147F5  |. 74 13          |JE SHORT SGS_NOCD.0041480A
004147F7  |. 33C0           |XOR EAX,EAX
004147F9  |. 8AC3           |MOV AL,BL
004147FB  |. A3 84054200    |MOV DWORD PTR DS:[420584],EAX
00414800  |. C705 80054200 >|MOV DWORD PTR DS:[420580],6
0041480A  |> FF35 D0754200  |PUSH DWORD PTR DS:[4275D0]              ; /hMutex = NULL
00414810  |. E8 86450000    |CALL <JMP.&KERNEL32.ReleaseMutex>       ; \ReleaseMutex
00414815  |. E9 5C0C0000    |JMP SGS_NOCD.00415476

[1C]
There is no opcode [1C].

[1F]
Code: [Select]
00414917  |> 833D A0054200 >|CMP DWORD PTR DS:[4205A0],0             ;  Case 1F of switch 00413F2B
0041491E  |. 0F85 520B0000  |JNZ SGS_NOCD.00415476
00414924  |. 833D A4054200 >|CMP DWORD PTR DS:[4205A4],0
0041492B  |. 0F84 450B0000  |JE SGS_NOCD.00415476
00414931  |. 33C0           |XOR EAX,EAX
00414933  |. A3 AC054200    |MOV DWORD PTR DS:[4205AC],EAX
00414938  |. C705 80054200 >|MOV DWORD PTR DS:[420580],7
00414942  |. E9 2F0B0000    |JMP SGS_NOCD.00415476

[26]
Code: [Select]
00414A6D  |> FF0D 6C054200  |DEC DWORD PTR DS:[42056C]               ;  Case 26 of switch 00413F2B
00414A73  |. A1 6C054200    |MOV EAX,DWORD PTR DS:[42056C]
00414A78  |. 8B0485 A875420>|MOV EAX,DWORD PTR DS:[EAX*4+4275A8]
00414A7F  |. 8906           |MOV DWORD PTR DS:[ESI],EAX
00414A81  |. E9 F0090000    |JMP SGS_NOCD.00415476

[27][XX]
Code: [Select]
00414A86  |> 8B06           |MOV EAX,DWORD PTR DS:[ESI]              ;  Case 27 of switch 00413F2B
00414A88  |. FF06           |INC DWORD PTR DS:[ESI]
00414A8A  |. 0FB600         |MOVZX EAX,BYTE PTR DS:[EAX]
00414A8D  |. 50             |PUSH EAX                                ; /Arg1
00414A8E  |. E8 1DDCFFFF    |CALL SGS_NOCD.004126B0                  ; \SGS_NOCD.004126B0
00414A93  |. 59             |POP ECX
00414A94  |. E9 DD090000    |JMP SGS_NOCD.00415476

[2D]
Code: [Select]
00414D3B  |> 33C0           |XOR EAX,EAX                             ;  Case 2D of switch 00413F2B
00414D3D  |. A3 70054200    |MOV DWORD PTR DS:[420570],EAX
00414D42  |. 33C0           |XOR EAX,EAX
00414D44  |. A3 74054200    |MOV DWORD PTR DS:[420574],EAX
00414D49  |. E9 28070000    |JMP SGS_NOCD.00415476

[35][XX]
Code: [Select]
00414E8F  |> 8B06           |MOV EAX,DWORD PTR DS:[ESI]              ;  Case 35 of switch 00413F2B
00414E91  |. 8A18           |MOV BL,BYTE PTR DS:[EAX]
00414E93  |. FF06           |INC DWORD PTR DS:[ESI]
00414E95  |. 33C0           |XOR EAX,EAX
00414E97  |. 8AC3           |MOV AL,BL
00414E99  |. 66:FF0445 3C6E>|INC WORD PTR DS:[EAX*2+426E3C]
00414EA1  |. E9 D0050000    |JMP SGS_NOCD.00415476

[36][XX]
Code: [Select]
00414EA6  |> 8B06           |MOV EAX,DWORD PTR DS:[ESI]              ;  Case 36 of switch 00413F2B
00414EA8  |. 8A18           |MOV BL,BYTE PTR DS:[EAX]
00414EAA  |. FF06           |INC DWORD PTR DS:[ESI]
00414EAC  |. 33C0           |XOR EAX,EAX
00414EAE  |. 8AC3           |MOV AL,BL
00414EB0  |. 66:FF0C45 3C6E>|DEC WORD PTR DS:[EAX*2+426E3C]
00414EB8  |. E9 B9050000    |JMP SGS_NOCD.00415476

[37][XX][[XXXX]]
Code: [Select]
00414EBD  |> 8B06           |MOV EAX,DWORD PTR DS:[ESI]              ;  Case 37 of switch 00413F2B
00414EBF  |. 8A18           |MOV BL,BYTE PTR DS:[EAX]
00414EC1  |. FF06           |INC DWORD PTR DS:[ESI]
00414EC3  |. 8B06           |MOV EAX,DWORD PTR DS:[ESI]
00414EC5  |. 66:8B00        |MOV AX,WORD PTR DS:[EAX]
00414EC8  |. 33D2           |XOR EDX,EDX
00414ECA  |. 8AD3           |MOV DL,BL
00414ECC  |. 66:010455 3C6E>|ADD WORD PTR DS:[EDX*2+426E3C],AX
00414ED4  |. 8306 02        |ADD DWORD PTR DS:[ESI],2
00414ED7  |. E9 9A050000    |JMP SGS_NOCD.00415476

[39][XX][[XXXX]]
Code: [Select]
00414EFB  |> 8B06           |MOV EAX,DWORD PTR DS:[ESI]              ;  Case 39 of switch 00413F2B
00414EFD  |. 8A18           |MOV BL,BYTE PTR DS:[EAX]
00414EFF  |. FF06           |INC DWORD PTR DS:[ESI]
00414F01  |. 8B06           |MOV EAX,DWORD PTR DS:[ESI]
00414F03  |. 66:8B00        |MOV AX,WORD PTR DS:[EAX]
00414F06  |. 33D2           |XOR EDX,EDX
00414F08  |. 8AD3           |MOV DL,BL
00414F0A  |. 66:210455 3C6E>|AND WORD PTR DS:[EDX*2+426E3C],AX
00414F12  |. 8306 02        |ADD DWORD PTR DS:[ESI],2
00414F15  |. E9 5C050000    |JMP SGS_NOCD.00415476

[3A] - ??
The program went nuts when it reached this opcode. I'll try other approach later.

[3F]
There is no opcode [3F].

[43][[XXXX]]
Code: [Select]
0041528B  |> 8B06           |MOV EAX,DWORD PTR DS:[ESI]              ;  Case 43 of switch 00413F2B
0041528D  |. 0FB700         |MOVZX EAX,WORD PTR DS:[EAX]
00415290  |. A3 E8044200    |MOV DWORD PTR DS:[4204E8],EAX
00415295  |. 8306 02        |ADD DWORD PTR DS:[ESI],2
00415298  |. E9 D9010000    |JMP SGS_NOCD.00415476

[44][XX]
Code: [Select]
0041529D  |> C705 80054200 >|MOV DWORD PTR DS:[420580],0A            ;  Case 44 of switch 00413F2B
004152A7  |. E9 CA010000    |JMP SGS_NOCD.00415476

[46]
Code: [Select]
004152C7  |> 803D 4C054200 >|CMP BYTE PTR DS:[42054C],0              ;  Case 46 of switch 00413F2B
004152CE  |. 0F84 A2010000  |JE SGS_NOCD.00415476
004152D4  |. C705 80054200 >|MOV DWORD PTR DS:[420580],0B
004152DE  |. E9 93010000    |JMP SGS_NOCD.00415476

[47][XX]
Code: [Select]
004152E3  |> 8B06           |MOV EAX,DWORD PTR DS:[ESI]              ;  Case 47 of switch 00413F2B
004152E5  |. FF06           |INC DWORD PTR DS:[ESI]
004152E7  |. 0FB600         |MOVZX EAX,BYTE PTR DS:[EAX]
004152EA  |. 50             |PUSH EAX                                ; /Arg1
004152EB  |. E8 5BDBFFFF    |CALL SGS_NOCD.00412E4B                  ; \SGS_NOCD.00412E4B
004152F0  |. 59             |POP ECX
004152F1  |. E9 80010000    |JMP SGS_NOCD.00415476

[49][XX][[XXXX]]
Code: [Select]
00415322  |> 8B06           |MOV EAX,DWORD PTR DS:[ESI]              ;  Case 49 of switch 00413F2B
00415324  |. 0FB600         |MOVZX EAX,BYTE PTR DS:[EAX]
00415327  |. 8945 F8        |MOV DWORD PTR SS:[EBP-8],EAX
0041532A  |. FF06           |INC DWORD PTR DS:[ESI]
0041532C  |. 8B06           |MOV EAX,DWORD PTR DS:[ESI]
0041532E  |. 0FB638         |MOVZX EDI,BYTE PTR DS:[EAX]
00415331  |. 4F             |DEC EDI
00415332  |. FF06           |INC DWORD PTR DS:[ESI]
00415334  |. 8B06           |MOV EAX,DWORD PTR DS:[ESI]
00415336  |. 0FB600         |MOVZX EAX,BYTE PTR DS:[EAX]
00415339  |. 8945 F4        |MOV DWORD PTR SS:[EBP-C],EAX
0041533C  |. FF06           |INC DWORD PTR DS:[ESI]
0041533E  |. 57             |PUSH EDI                                ; /Arg2
0041533F  |. FF75 F8        |PUSH DWORD PTR SS:[EBP-8]               ; |Arg1
00415342  |. E8 6FDBFFFF    |CALL SGS_NOCD.00412EB6                  ; \SGS_NOCD.00412EB6
00415347  |. 83C4 08        |ADD ESP,8
0041534A  |. 25 FF000000    |AND EAX,0FF
0041534F  |. 8B55 F4        |MOV EDX,DWORD PTR SS:[EBP-C]
00415352  |. 66:890455 3C6E>|MOV WORD PTR DS:[EDX*2+426E3C],AX
0041535A  |. E9 17010000    |JMP SGS_NOCD.00415476

While looking at these, I've found that [2F], [30] and [31] are conditional jumps (updated my list). I'm hoping to get some free time in the following days so until then, I won't be able to dedicate myself to this :(
Title: Re: SOGNA's WIN Format
Post by: JG on November 13, 2010, 07:09:02 pm
That's fantastic work, golden.  I don't suppose you could do that for all the opcodes could you?  Being able to compare these assembler statements against known opcodes's assembler statements would be a big help (especially in decoding all these conditional jumps)

Also, whenever you see a CALL statement that isn't an API function (like CALL SGS_NOCD.00411BF3) I'd need the assembler statements for that block of code (starting at 00411BF3).  I'm unable to tell what these statements are doing yet.

You did confirm my suspicions about INC, DEC, ADD, OR, and AND though.  In that same range of codes is [3A], which I think might be SUB, and you ended up subtracting to less than zero causing an overflow in the SGS engine. Maybe ensure your register has a large value and then subtract a smaller value, like so:

34 01 0A 00  ; WRITE REGISTER=1 VALUE=10
3A 01 05 00  ; SUBTRACT REGISTER=1 VALUE=5

If it turns out to be a multiply (or even a divide) this still shouldn't crash with these values.
Title: Re: SOGNA's WIN Format
Post by: golden on November 14, 2010, 09:57:43 am
Also, whenever you see a CALL statement that isn't an API function (like CALL SGS_NOCD.00411BF3) I'd need the assembler statements for that block of code (starting at 00411BF3).  I'm unable to tell what these statements are doing yet.

Of course, sorry, I didn't notice those. But it would take too much time to do that for all opcodes because of subsequent calls within calls; tell you what, some opcodes might be easy to figure without having to explore those calls and for the opcodes that we can't figure out, I'll print those calls as well.

In the meantime, here's a file with the ASM for all opcodes:
http://dl.dropbox.com/u/2910075/opcode%20table.txt
Title: Re: SOGNA's WIN Format
Post by: JG on November 14, 2010, 08:24:45 pm
In the meantime, here's a file with the ASM for all opcodes:
http://dl.dropbox.com/u/2910075/opcode%20table.txt

Thanks, I'll let you know what is still outstanding after I've gone through this.


UPDATE:
I've gotten through about half of it and it's helped clear up what some of the codes (08, 09, 0B, 0D, 16, 18, and 1F) might be doing.  These I've now confirmed though:

[21][pixels]
Set line spacing for currently active text box.  This is actually the vertical kerning space. A value of 2 is normal for the font, in that it reserves one pixel above and one pixel below most font glyphs.  Some characters, mostly punctuation but some lowercase types like p and q will drawn into this area.  A value less than 2 can cause the lines to partially draw over each other.

[25][[to]]
This is a GOSUB (or CALL if you prefer that terminology).  There is no condition being checked.  It's simply storing the address it jumped from (plus 2 bytes) to a small array at 4275A8 and incrementing a nesting counter at 42056C.

[26]
This is the RETURN for opcode 25.  Please note that it does not check if the nesting counter at 42056C is already zero, so it can underflow.  This will undoubtedly crash the SGS engine.


It's midnight now so I have to stop working on it tonight - but making great progress.
Title: Re: SOGNA's WIN Format
Post by: JG on November 15, 2010, 08:11:59 pm
More confirmations:

[2B][[address]]
Enable load menu.  The address is stored and used by some other action.  I presume this location would be jumped to upon selection of a grayed out submenu item which shouldn't ever happen, but perhaps SGS has a mode to allow program instructions to be run if a nonexistant save state is selected, for example, printing a message to the screen as most other games do.  (I haven't quite figured this out yet. Opcode 29 does the same thing, but I'm not 100% sure it operates on the exit menu yet.)

[2C]
Disable load menu.  Since the entire menu is disabled, none of the submenus are available and thus no need for an address argument like 2B has.

[3A][[cycles]]
Fade out the palette.
Not the same as 06 though they appear to have the same visual effect.  06 looks like it modifies the alpha channel of a layer covering the viewport to accomplish a fade out where 3A actually modifies the red, green, and blue channels of the viewport itself over time.  Thus, you can undo 06 by opcode 05 but to undo 3A you need to use 28 (or 41) and redefine your palette colors (becuase they're now all zeroed out)

[40][enable]
Set save menu state.  Disabled if argument is 0; enabled otherwise.
Note that this doesn't require seperate enable and disable operations like the load menu does, becuase its impossible to select an invalid option.
Title: Re: SOGNA's WIN Format
Post by: JG on November 16, 2010, 06:58:08 pm
Ok, I finished going through the opcode assembly.  I've managed to map a great deal of the SGS system memory, but theres some variables I don't know the purpose of yet.  And some of the CALL functions hide what the opcode is doing, so I've got to go through these functions now:

Assembly code starting at following memory locations and continuing until the RETN:
411B4D (opcodes 03 and 04 - may perform some kind of viewport reset; 1 = invalidate client area, 0 = revalidate client area?)
412DA0 (opcodes 0E and 0F)
411BF3 (opcode 10)
411C28 (opcode 12)
4126B0 (opcode 27)
412972 (opcode 3B - we know what this opcode does but I need the code to compare against 3C)
4128FA (opcode 3C - I suspect this resets the volume and other system properties stored in registry)
412E4B (opcode 47)
412EB6 (opcode 49)


And also figure out what references the following memory locations:
420580 (this is some kind of system state variable; about a third of the opcodes set it but I haven't discovered its purpose yet)
420550, 42055C, 420564, and 420580 (opcodes 08 and 09)
423434 (opcodes 0A, 0B, 0C, 0D,a nd 18 - the bytes at this location indicate ANM properties)
423435 (opcodes 0A and 18)
420584 (opcodes 0C and 18)
420570 (opcode 15)
420574 (opcode 16)
42345C (opcode 17)
426BB4 (opcode 3E)
42758C (opcode 42)
4204E8 (opcode 43)
42054C (opcodes 45 and 46)



I think I found the debugger you were using (OllyDbg?) so I've managed to disassemble SGS in the same format you used.
Title: Re: SOGNA's WIN Format
Post by: JG on November 16, 2010, 10:27:56 pm
A couple of more confirmations:

[04][image]
Unload ANM.  Probably rarely used.  Since only 8 ANMs can be loaded at once, it might see more usage in later games (unless they allow more than the 8 ANMs that V6 does)

[0F]
Wait for keyboard or mouse input.  Exact same as 0E.
There is a boolean state flag at 4204AC that is set to 1 by both codes.  It may be that one of these two was intended to set 4204AC to 0 instead (later games might actually use 0F with a corrected flag value of 0)

[3B]
Clears state (as stored in registry keys SystemFlag and SaveSystem), see 3C

[3C]
Save state (as stored in registry keys SystemFlag and SaveSystem)
SystemFlag is a boolean in V6 (0 or 1), but I noticed later games use other bits.
SaveSystem is a copy of the first N register values (for V6 and V8, the first 16; haven't checked later games yet)
This could be used in conjunction with opcode 47 to allow save states controlled by code.



And partially confirmed:

[27][boolean]
Set full screen window mode? As best I can tell argument of 0 would set regular window mode, and value of 1 sets full screen mode.  If one of you guys can actually test this opcode in a custom WIN file, we'll know for sure.  (If not, I'll try it when I get my compiler working; still working on the decompiler now.)

[47][byte]
Resets a large number of flags.  Not sure what the byte value is used for yet.
Title: Re: SOGNA's WIN Format
Post by: JG on November 22, 2010, 07:53:12 pm
Update: No new work on determining opcode functionality.  I've instead been rewriting my decompiler to produce arrays of operation objects which contain arrays of argument objects which perform all the reading and writing to byte arrays and text.  While this complicates the decompiler I had (which wrote straight out to text) it will greatly simplify the compiler and allow me to collect some stats, such as how often certain opcodes are used, whether they precede certain opcodes or follow them, etc, and allow me to more easily capture key operations (like load_anm and set_anm_properties) to automate accurate animated GIF creation.  I've gotten to the point that my decompiler is back to the same functionality it was before while covering about half the code I need for the compiler (still need to write several text parsing functions to have a working compiler)

Hopefully will get some time to work on it over the Thanksgiving holiday, but will be in North Carolina most of the rest of the week, so don't count on it.
Title: Re: SOGNA's WIN Format
Post by: golden on November 22, 2010, 09:29:29 pm
I think I found the debugger you were using (OllyDbg?) so I've managed to disassemble SGS in the same format you used.

Yeah, I've been using Olly. I'd really like to help but I've been postponing work on my MSc thesis and I need to do some serious work on it for the following weeks or my mentor will flip out. But I'll be following this thread and when my schedule clears a bit I'll help you out.
Title: Re: SOGNA's WIN Format
Post by: JG on November 23, 2010, 07:20:02 am
Totally understand.  I'm glad I had the option of a project instead of a thesis when I did my masters.
Title: Re: SOGNA's WIN Format
Post by: 黒い灯影 on December 08, 2016, 06:26:18 pm
Just my luck, the PHP module froze, as I was about to post something, lost most of what i wrote, got distracted by something else online  xD

Anyways, I was dusting off my old research notes,
Working off of RSR's 544.AMN

Code: [Select]
0A00 0000 0000 0180 0100 0103 0103 0103 0103 0103 0103 0103 0103
0A01 0000 0000 0380 000C 0103 0203 0303 0403 0503 0403 0303 0203

0A is the ANMsequence opcode,
byte - layer
word - OffsetX
word - OffsetY
byte - mode? (01  = no transparent,02 = run once,03 = loop w/ transparent,04 - 06 = invisible)
byte - not sure what this is(0x80)
byte - backgroundFlag?  frame01 becomes last image in ANM file, 02-7F crashes, 80-FF doesn't render a frame
byte - Color Palette Transparency Color (from the ANM's color palette) 0C is usually the blue color
then
[byte, byte] pairs until 0x00
Title: Re: SOGNA's WIN Format
Post by: 黒い灯影 on December 08, 2016, 08:06:21 pm
also, i dont know what to do with this
I coded my own WIN script reader, just outputs to plain text
and came across this, opcode [11]

This was from V16 I's DAY6B.WIN script.

of course, i could have made a mistake with my programming, but im pretty sure, everything is correct up until this point
Title: Re: SOGNA's WIN Format
Post by: JG on December 09, 2016, 08:52:53 am
You've got something wrong in the previous opcode you have starting at 0x0F90.

The frames argument always comes in byte pairs. 15,0 is the first pair. You're incorrectly interpetting that zero as the termination byte, causing the 18,2 and 19,2 frames following it to run the wrong code up to the point of the 17,2 entry. 17 = 0x11.  There is no opcode 0x11 - it's probably something that was needed in PC98 but not in Windows.

I don't know why your addressing scheme is different, but this is the same block code extracted using my tool:

0x1B28: WRITE REGISTER=16 VALUE=40
0x1B2C: LOAD_ANM IMAGE=0 FILE="ANM\Y40"
0x1B36: CLEAR_IMAGE_PROPERTIES BUFFER=1
0x1B38: SET_IMAGE_PROPERTIES IMAGE=0 OFFSET=52 BUFFER=1 LEFT=0 TOP=0
0x1B40: SET_PALETTE_FROM_ANM IMAGE=0
0x1B42: ENABLE_ANIMATION_PAUSE
0x1B43: SET_BUFFER_PROPERTIES BUFFER=0 LEFT=0 TOP=0 FLAGS=0x8000 IMAGE=1 MASK_COLOR=0x00 FRAMES=(1:3, 1:3, 1:3, 1:3, 1:2)
0x1B58: SET_BUFFER_PROPERTIES BUFFER=1 LEFT=0 TOP=0 FLAGS=0x8002 IMAGE=0 MASK_COLOR=0x0C FRAMES=(28:3, 29:3, 30:3, 31:3, 32:2)
0x1B6D: DISABLE_ANIMATION_PAUSE
0x1B6E: FADE_IN_VIEWPORT_GRAYSCALE COLOR=0x00 CYCLES=1
0x1B72: WAIT_FOR_BUFFER_FRAMES BUFFER=0
0x1B74: SET_BUFFER_PROPERTIES BUFFER=1 LEFT=0 TOP=0 FLAGS=0x8003 IMAGE=0 MASK_COLOR=0x0C FRAMES=(15:0, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 16:2, 17:2, 15:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2, 19:2, 18:2)
0x1BE7: PLAY_PCM STREAM=0 FILE="PCM\IM200022"

Title: Re: SOGNA's WIN Format
Post by: 黒い灯影 on December 09, 2016, 09:10:24 am
you're right, i JUST noticed that, just now, the 00 ends that part prematurely in my code
that IS strange that the offsets dont match up.  either my WIN script is messed up but it does match up when i open the scripts in a hex editor