AGS 3.3.0 Release Candidate

Started by Crimson Wizard, Thu 04/04/2013 19:16:28

Previous topic - Next topic

Radiant

And we've got a crash.

Relevant code is:
  if (action == 97) {
    FadeOut        (4);
    RawClearScreen (0); // crash on this line
    GUIOff         (BONUS);
    Wait           (1);
    FadeIn         (64);
    RestartGame    ();
  }

Exception 0xc0000005, at EIP 0x0043bd77, prog ptr +6, 3.3.0.1144, gtags 45, 7. I can send you a crash.dmp file if you think it helps.

Crimson Wizard

#301
Quote from: Radiant on Sun 06/10/2013 18:57:11
And we've got a crash.

Oops.
Fixed acwin.exe:
http://www.mediafire.com/download/9cxx8j4x7eg1g5v/acwin.exe

There will be Beta 9 in a short while, with few more additions.

Radiant

Thank you very much. Could you perhaps advice us on thw Win8 music issue please?

Crimson Wizard

Quote from: Radiant on Sun 06/10/2013 19:27:59
Thank you very much. Could you perhaps advice us on thw Win8 music issue please?
Audio is a part of AGS I did not investigate much yet.
Here I built an engine version with multithreaded audio disabled:
http://www.mediafire.com/download/f8gfo28hf1fzdka/acwin_no_threaded_audio.zip
Perhaps you could try to use it instead and see if that changes anything.

AGD2

Crimson Wizard, was anything ever looked into regarding the issue with Pamela lip-syncing not working with speech files when multithreaded audio is enabled?

If not, could you make multithreading an option which the game developer can set? I have over 5,000 lip-synched lines and the multithreading murders every one of them. :~(

Crimson Wizard

Quote from: AGD2 on Sun 06/10/2013 20:28:23
Crimson Wizard, was anything ever looked into regarding the issue with Pamela lip-syncing not working with speech files when multithreaded audio is enabled?

If not, could you make multithreading an option which the game developer can set? I have over 5,000 lip-synched lines and the multithreading murders every one of them. :~(

Err... I wasn't aware of this at all (also I never tested nor played a game with Pamela lip-sync, so I vaguely know how this works).
Audio multithreading was originally made for some of the mobile ports to speed them up a bit. I guess this lipsync incompatibility was overlooked.
Yes, I guess it would be proper to add such setting, since it breaks things.

AGD2

In AGS's "Lip sync" tab, you specify which Pamela phonemes (mouth positions) should correspond to each frame in your character's talking view. In other words, each phoneme frame represents a unique sound a person makes while talking. You can assign more than one phoneme to a view frame. Below is a list of all the phonemes Pamela uses, and how I have personally set them up in the AGS "Lip Sync" tab:

0 (Mouth Closed): ZH/None
1 (A Frame): AY0/AY1/AY2/AA0/AA1/AA2/AH0/AH1/AH2/AE0/AE1/AE2
2 (W Frame): W/OW0/OW1/OW2/OY0/OY1/OY2/UW0/UW1/UW2
3 (E, C, & K frame): EH0/EH1/EH2/CH/ER0/ER1/ER2/EY0/EY1/EY2/G/K/R/Y/HH
4 (S & Z frame): S/Z/IH0/IH1/IH2/IY0/IY1/IY2/SH
5 (F & V frame): F/V
6 (T & N frame): T/TH/D/DH/JH/N/NG
7 (L & TH frame): L
8 (O & U frame): AO0/AO1/AO2/AW0/AW1/AW2/UH0/UH1/UH2
9 (B, M, & P frame): B/M/P

It doesn't really matter how you set them up, this just shows how I've done it, and it covers every single phoneme used in Pamela. For each of these 9 frames, you'd create a speech graphic for your character's dialog portrait in Photoshop (or similar) with his mouth in that visual position.

Next, you open a WAV character speech file in the Pamela utility. You drag vertical bars (which represent the above phonemes) into various positions along the WAV timeline. These bars tell Pamela which points in the WAV file each visual frame should be displayed. When you've finished positioning all the bars and have set them to the correct phonemes, you finally save a .pam file which corresponds with the character's speech file you just opened. So, EGO1.wav would correspond with EGO1.pam. Here's an example of the contents of a short .pam file where the character says "Do you sell sunscreen?"

Spoiler

[Speech]
225:L
555:ZH
390:S
360:N
75:Y
45:AO0
270:S
15:D
435:AY0
180:AY0
150:S
120:W
90:AO0
315:AO0
525:T

[Preferences]
translationfile:sample.mot
soundfile:C:/pam/EGO1308.wav
framespersecond:24
textdata:Do you sell sunscreen?
framesperphoneme:3
[close]

As you can see, each phoneme is preceded by a timing number which determines when that phoneme should play (and thus, when the corresponding View/frame for the dialog portrait is shown in AGS). When watching the talking portrait in-game, each phoneme (visual mouth frame) is held until the timer reaches the next phoneme along the timeline, and then it is replaced by the newer one.

At the moment,  multithreaded audio throws off the timing, presumably because multithreading pre-buffers the audio and AGS relies on the speech playing real-time so that it can use the correct timing in the .pam files. I could be wrong about this - I'm not actually sure how it's coded, but if this is the case, I was wondering if a possible solution would be for the engine to run an independent timer alongside speech audio. Whenever Say(), or legacy DisplaySpeech(), is used, an integer timer could start counting. Then the .pam file could take its cues from this integer timer, rather than taking them directly from the speech audio file.

Giving the option to disable and enable multithreaded audio is good, but obviously, the music stutter is a real pain too. So if the issue can be resovled entirely, then even better! :D

Radiant

There appears to be something wrong with old-style strings as well. The following code works fine in older versions, but not in 3.3:

function CallItemLook (int num) {
  string buf;
  if (num == Money) {
    StrFormat (buf, "You have %d silver coins. They are of negligible weight.", player.inv[Money]);
    disp (buf);
  }
}

function disp (const string s1, const String s2) {
  if (game.skipping_cutscene) return;
  String inp, msg;
  int    ch, xs, ys;
  inp = s1;
  // now inp becomes an empty string...
}

Radiant

And a feature request. Our resident artists would like portrait animation speed to stay constant if you increase game speed. I suppose that sounds counterintuitive :) but perhaps using game.talkanim_speed there may be some possibilities there? Or perhaps I could figure out some math if you could tell me how game.talkanim_speed actually works; right now I'm setting game.talkanim_speed to GetGameSpeed() / 7, but that's not a very smooth result.

monkey0506

Although it should still work, is there a reason you're using old-style strings? You could replace the StrFormat with String.Format which returns a new-style String, which is compatible with const string (but not string). Of course you only ever need const string if you're intermixing new- and old-style strings. Switching from strings to Strings is pretty simple, and you'll find that it makes your life a lot easier.

The only time I can think of when using old-style strings would still be useful is if you're appending a bunch of single characters together. The new-style String type is (rather foolishly IMO) totally immutable, so append is a particularly expensive operation. If you use an old-style string then it's significantly less expensive. It would be very worthwhile to replace the internals of String with a mutable type that prefers over-allocation to re-allocation. But that's another topic, and just points out how little I've done for AGS. :P

Old-style strings should still be functional though.

Radiant

It's years-old code; I believe there was some functionality in the past that existed in oldstyle strings but not in newstyle, and it probably does now. I suppose I should clean up my code some time and move to newstyle strings at some point, but as long as everything works other things take up my time first.

Radiant

And there's another discrepancy with fade sequences. I have a room set up like this:


DynamicSprite *d1;
int ht, ft;

room function called from on_event (ENTER_ROOM) {
  int i;
  if (event == 0) {
      d1       = DynamicSprite.CreateFromBackground ();
      SetObjectTransparency (1, 100);
      SetObjectTransparency (2, 100);
      SetObjectTransparency (3, 100);
      SetObjectTransparency (10,100);
      RawClearScreen (0);
    }
  }

room function called from first tick of repeatedly_execute {
  if (event == 1) {
    i = 98;
    while (i > 2) {
      RawClearScreen          (0);
      RawDrawImageTransparent (0, 0, d1.Graphic, 100 - i);
      SetObjectTransparency   (1, i);
      SetObjectTransparency   (2, (i / 2) + 50);
      SetObjectTransparency   (3, i);
      SetObjectTransparency   (10,i);
      SetObjectTransparency   (4, 100 - i);
      SetObjectTransparency   (5, 100 - i);
      SetObjectTransparency   (6, 100 - i);
      SetObjectTransparency   (7, 100 - i);
      SetObjectTransparency   (8, 100 - i);
      SetObjectTransparency   (9, 100 - i);
      Wait                    (1);
      i -= 2;
    }
    i = 4;
    while (i <= 9) {
      ObjectOff (i);
      i ++;
    }
    RawDrawImage (0, 0, d1.Graphic);
    d1.Delete    ();
  }


So what this should do is fade in a black room with a few objects visible, then fade out those objects while fading in the actualy background (stored in a dynamicsprite). What actually happens in 3.3 is that the fading of the room background is reversed, i.e. it appears at full then fades to black, then snaps to full again.

Crimson Wizard

#312
You know... It looks like it is previous versions of AGS that had a bug...

Let me explain.
If you read a 2.72 manual, it states:
Code: ags

RawDrawImageTransparent(int x, int y, int slot, int transparency)

Draws image SLOT from the sprite manager onto the screen at location (X,Y), with a translucency of TRANSPARENCY percent.
TRANSPARENCY is from 0-100; passing a TRANSPARENCY of 50 will draw the image semi-transparent; passing 0 is equivalent to just calling the normal RawDrawImage command.

<...>
RawDrawImageTransparent(100, 100, 134, 75);

will draw sprite 134 at (100, 100) on the screen, with 75 percent transparency.


Now, you call this:
Code: ags
 RawDrawImageTransparent (0, 0, d1.Graphic, 100 - i);

starting with i = 98, that is with transparency = 100 - 98 = 2.
That are 2% of transparency.
Yet 3.2.1 (and probably earlier) AGS draws image 98% transparent (2% opaque)!

Basically, this function acts opposite to how it is explained in the manual.
This is because there is (was) a mistake in the code, which used transparency argument in reverse way... and I occasionally fixed that mistake some time ago. :-\

Radiant

That's a good point, I remember being confused by this function in the past. But it does break backwards compatibility, so I'll leave it to you guys to decide how to deal with this.

Radiant

Quote from: Crimson Wizard on Sun 06/10/2013 20:09:18
Here I built an engine version with multithreaded audio disabled:
http://www.mediafire.com/download/f8gfo28hf1fzdka/acwin_no_threaded_audio.zip
Perhaps you could try to use it instead and see if that changes anything.
This appears to fix (or avoid) the issue, yes.

Radiant

#315
I've thought of something else that would cost you probably 15 minutes to implement and could save hours of future debugging. There are occasions where AGS terminates with an error message, but the message doesn't give me the information I need to find the error. It would be really helpful if you could include that in the message text.

The messages I'm talking about are,

  • Array out of bounds. It's great to know the allowed range, but what I'd really like to see is the name of the array.
  • SetCharacterFrame, GetGameParameter (GP_FRAMEIMAGE), GetGameParameter (GP_ISFRAMEFLIPPED) if the loop or frame number is out of bounds; please specify which view/loop/frame the function was called with. (by the way you'll probably ask why I use this deprecated function? It's because a single call to GetGameParameter returns the integer I need, and I find this cleaner than obtaining a viewframe pointer via Game.GetViewFrame, then using that pointer to get at the data)
  • Starting cutscene while already in a cutscene. I get the line number of the new cutscene, but it would be great to have the line number of the first one (because that's generally where the error is - a missing EndCutscene call). The same applies to NewRoom while a new room is already triggered in the same script cycle

Thank you for your time :)

Crimson Wizard

#316
Quote from: Radiant on Mon 07/10/2013 10:31:19
  • Array out of bounds. It's great to know the allowed range, but what I'd really like to see is the name of the array.
Name of variables are never stored in game, only addresses in memory. This would require rewriting the agsscript compiler, at least.
Array size can be added to the error message, indeed. Right.

Radiant

Ah, that explains it. Well never mind that one, then :) The array size is already there, it says "0..19" for the range.

Crimson Wizard

#318
Okay, here's another updated acwin.exe:
http://www.mediafire.com/download/6kb9e1x19nq9xpi/acwin.exe

- Fixed old strings assignment to new ones (and also when using in equality operators).
- Fixed RawDrawImageTransparent to work like it did.
BTW, things are really messy here. Quote from CJ found in code:
Quote
Transparency is a bit counter-intuitive
0 = not transparent, 100 = invisible, 1..99 barely visible .. mostly visible
Same goes for Object and Character.Transparency. (wtf)

No multithreaded audio in this one.

Also added extra info to error messages, as was asked.


EDIT: As a note to other devs: I did not push these changes to repository yet. I want to be sure this works first (some tricky changes there).

Radiant


SMF spam blocked by CleanTalk