Difference between revisions of "User:Buddha^/GSoC2007-ProjectDiary"

Jump to navigation Jump to search
Fixed link (palex.py -> agi-palex.py)
(Added done work on 2007-07-24.)
(Fixed link (palex.py -> agi-palex.py))
 
(89 intermediate revisions by the same user not shown)
Line 1: Line 1:
= [[User:Buddha^|Buddha^]]'s Google Summer of Code 2007 Project Diary =
Here's the archive of the project diary I kept during my
Google Summer of Code 2007 participation.
== 2007-05-28 (Monday) - GSoC starts! ==
== 2007-05-28 (Monday) - GSoC starts! ==


Line 646: Line 651:


So I made a tool for extracting palettes from Amiga AGI games' executable files
So I made a tool for extracting palettes from Amiga AGI games' executable files
and added it to ScummVM's trunk. You can see the source code [http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/tools/palex.py?revision=28035&view=markup here].
and added it to ScummVM's trunk. You can see the source code [http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/tools/agi-palex.py?revision=28035&view=markup here].
My first Python program, yay!
My first Python program, yay!


Line 806: Line 811:
fever coming on... we'll see.
fever coming on... we'll see.


Took a look at the current Apple IIGS sound implementation in ScummVM. Loaded up some
Took another look at the current Apple IIGS sound implementation in ScummVM. Loaded up some
resource files (The *vol.* files) from Apple IIGS AGI games as raw 8 bit unsigned 8kHz
resource files (The *vol.* files) from Apple IIGS AGI games as raw 8 bit unsigned 8kHz
sample data into Audacity and pressed play: MIAUUU! PRRRR! SQUEAAK!
sample data into Audacity and pressed play: MIAUUU! PRRRR! SQUEAAK!
KRRRKRRRRKRRRRRRRRRR! "All aboard!" etc. Yeah, there's sample data in there alright :-).
KRRRKRRRRKRRRRRRRRRR! "All aboard!" etc. Yeah, there's sample data in there alright :-).
== 2007-07-25 (Wednesday) - Dumping Apple IIGS sound files ==
Made ScummVM dump out the Apple IIGS MIDI and sample files and then converted
the samples to .au-format using Python (It's got a library for outputting .au-files
so it wasn't very hard). Here's a sound from Gold Rush:
[[media:gold_rush-apple_iigs-sample-068.au | A man yelling "All aboard!"]].
Possibly going to mess with [http://www.mess.org/ MESS] to better understand
how the sound works with Apple IIGS AGI games.
== 2007-07-26 (Thursday) - Some recreation ==
Took the day off and looked a bit at [http://en.wikipedia.org/wiki/Sanitarium_(videogame) Sanitarium]
with IDA among other things. And had some snails and onion soup :).
BTW Sanitarium uses Smacker for videos (There's a DLL so it's not hard to spot :-)).
And the game's main executable holds a nice collection of error and debug
messages that help reverse engineering.
== 2007-07-27 (Friday) - Apple IIGS sample loading ==
Made routines for loading Apple IIGS AGI sample resources and making
audio streams out of them. Took influence from the AIFF-loading routine
from ScummVM's source code.
== 2007-07-28 (Saturday) - Decoding Apple IIGS sample header, Part 1 ==
Modified a byte in an Apple IIGS AGI sample resource's header (At
header offset 2) and tried the sample out by running the game
using KEGS32 and MESS. So it turned out that that header byte
handles playing pitch. And it's definitely exponential
with 2**(1/12) as the base. The value seems to wrap around after 0x7F.
== 2007-07-29 (Sunday) - Decoding Apple IIGS sample header, Part 2 ==
Inspected how the byte in Apple IIGS AGI sample resource's header
offset 4 affects the playing of the sample. It is the volume control,
probably logarithmic, but not 100% sure about that yet.
Fiddled a bit with some other header offsets and got something
interesting and/or weird to happen but don't yet know what they
really did :-).
The Apple IIGS AGI sample resource's header is 54 bytes long and
by the header comparisons I've done the following header offsets
are the most varying ones (Some other bytes also vary, but only
between two values in the data I've compared):
* Header offset 2
** The playing pitch
* Header offset 4
** Volume control
* Header offsets 8 and 9
** Sample size in bytes (Little endian 16-bit word)
* Header offset 44
** Unknown function, uses values x*9 for x in {0, 1, 2, 3, 4, 5, 6}
* Header offset 45
** Unknown function, uses values 0, 2, 6
* Header offset 50
** Unknown function, uses values x*9 for x in {1, 2, 3, 4, 5, 6}
* Header offset 51
** Unknown function, uses values 0, 1, 2, 7
== 2007-07-30 (Monday) - Locating Apple IIGS instruments and Atari ST and Apple IIGS palettes ==
Played with [http://hte.sourceforge.net/ HT Editor] to find out where the instrument
data is in different Apple IIGS AGI games. Found out the offsets into the games' executables
but haven't yet compared the instrument data between games to see how much of it is shared data.
Also looked into the SIERRASTANDARD-file that comes with Apple IIGS AGI games.
It's a 65536 bytes long file containing raw unsigned 8-bit mono PCM-audio data used
by the instruments. The file is identical between all the Apple IIGS AGI games I've
tested, excluding Space Quest I (It has a couple of different sounds).
As I was going through the Apple IIGS AGI executables in search for the instrument data
I also thought why not look for the palette data as well. Tried out a couple of possibilities
and finally found the palette with the search key (0xBB, 0x0B). As I had looked up from
Wikipedia that Apple IIGS used a 4096 (12-bit) palette it helped to narrow down the
search possibilities. Bytes 0xBB, 0x0B define an AGI palette color 7, which is gray.
So I looked through all the Apple IIGS game data I had for different palettes and compared
them.
According to the data I have compared there are two different Apple IIGS AGI palettes.
The first one is older and is only used in Space Quest I (AGI version 1.002) and it
is identical to the oldest generation [[User:Buddha%5E/GSoC2007-ProjectDiary#The_three_generations_of_Amiga_AGI_palettes | Amiga AGI palette]].
All other games (AGI versions 1.003 - 3.003) use a slightly different palette that's otherwise
identical to the first one but has a different color 13. Older palette uses an orange 0xF70
(12-bit RGB) there but all others use a light purple 0xD9F.
Just for the kicks I also looked through Atari ST AGI executables for palette data.
Wikipedia helped here again as it told me that the original Atari ST had a 64-color
palette. So after some searching I found the palette data. Extracted palettes from
all the Atari ST AGI executables I had access to and compared the data. I only
found a single identical palette shared between all of the Atari ST AGI games.
Here it is:
<pre>
/**
* Atari ST AGI palette.
* Used by all of the tested Atari ST AGI games.
* 16 RGB colors. 3 bits per color component.
*/
static const byte atariStAgiPalette[16 * 3] = {
0x0, 0x0, 0x0,
0x0, 0x0, 0x7,
0x0, 0x4, 0x0,
0x0, 0x5, 0x4,
0x5, 0x0, 0x0,
0x5, 0x3, 0x6,
0x4, 0x3, 0x0,
0x5, 0x5, 0x5,
0x3, 0x3, 0x2,
0x0, 0x5, 0x7,
0x0, 0x6, 0x0,
0x0, 0x7, 0x6,
0x7, 0x2, 0x3,
0x7, 0x4, 0x7,
0x7, 0x7, 0x4,
0x7, 0x7, 0x7
};
</pre>
== 2007-07-31 (Tuesday) - Comparing Apple IIGS instruments ==
Made a quick Python program for seeking out the instrument data from
Apple IIGS AGI executables and comparing them. I used a part of the first
instrument's starting data ('\x7f\x00\x0f\x78\x0a\x00\x78\x00\x00\x00\x14\x05')
as the search string. Here's what I found out:
There are two partially different instrument sets.
One is from the oldest test subject (Space Quest I using AGI 1.002)
and the other is from the newer games using AGI 1.003 - AGI 3.003.
Space Quest I has 26 instruments (1192 bytes), all others have 28 instruments (1292 bytes).
16 of the instruments are shared between the two data sets so
Space Quest I has 10 unique instruments. The unique instruments
are 2, 4, 13, 14, 17, 18, 20, 21, 22, 23 (Zero-based numbering).
All instruments are 44 bytes in length excluding instruments 6, 7 and 8
of the newer instrument set (And instruments that are identical with them,
of course). Instrument 6 of the newer instrument set is 80 bytes in length,
instruments 7 and 8 are 56 bytes.
Here are the starting offsets for instrument data in the tested Apple IIGS AGI executables:
* 0x80AD
** SQ.SYS16 (Space Quest I, AGI 1.002)
* 0x844E
** LL.SYS16 (Leisure Suit Larry I, AGI 1.003)
* 0x8469
** DEMO.SYS16 (AGI Demo 2, AGI 1.005)
** KQ.SYS16  (King's Quest I, AGI 1.006)
** PQ.SYS16  (Police Quest I, AGI 1.007)
* 0x84B7
** KQ2.SYS16 (King's Quest II, AGI 1.013)
** MG.SYS16  (Mixed-Up Mother Goose, AGI 1.013)
** KQ3.SYS16 (King's Quest III, AGI 1.014)
* 0x6563
** SQ2.SYS16 (Space Quest II, AGI 1.014)
* 0x8979
** MH.SYS16 (Manhunter I, AGI 2.004)
** KQ4.SYS16 (King's Quest IV, AGI 2.006)
** BC.SYS16 (The Black Cauldron, AGI 3.001)
** GR.SYS16 (Gold Rush, AGI 3.003)
BTW I also found out that by going 4 bytes backwards from the start
of the instrument data you'll find a little endian 16-bit
word giving the length of the whole instrument set (So it's
1192 with Space Quest I, 1292 with all the others).
== 2007-08-01 (Wednesday) - Instrument data, palette commits and Apple IIGS AGI debug mode triggers ==
Still played a bit with the Python program that handles the
Apple IIGS instrument data extraction. Now I feel like I'm
getting a bit of a hang of the instrument data.
Here's an odd bit of logic code I found from Apple IIGS
version of King's Quest I (I added the comments):
<pre>
if (v20 == 0) // v20 is computer type, value 0 is IBM-PC
  set.game.id("PQ"); // Police Quest?!
else
  set.game.id("KQ");
</pre>
Look at [[AGI/Specifications/Internals#Variables_used_by_the_interpreter | variables used by AGI]] for info on v20.
Like what? Why? Why would the game want to change its game ID
based on what computer it's being run on? Totally weird...
Also found some word triggers for Apple IIGS AGI debug modes:
* Police Quest I
** pqdbg
** stink bug
* King's Quest I
** kqdbg
* King's Quest II
** kq2dbg
* King's Quest III
** kq3dbg
** mice ass
* Space Quest II
** sq2dbg
Encountered CE in the games' version numbers (Example: "1.0K 11/22/88 CE")
and wondered about what it meant. After looking through some of the messages
in the logic resources I think CE probably means Carlos Escobar as he's credited as
the maker of (At least some - if not all - of) the Apple IIGS AGI versions.
Committed the Apple IIGS and Atari ST palettes to the trunk (Here's the
[http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/engines/agi/graphics.cpp?r1=28114&r2=28387&sortby=file diff]).
== 2007-08-02 (Thursday) - Trying to figure out Apple IIGS sample header ==
Tried to figure out what the unknown bytes in the Apple IIGS AGI sample resource's header do.
Finally figured out bytes at header offsets 44, 45, 50 and 51. According to my current
theory bytes 45 and 51 contain channel info and playing mode and bytes 44 and 50 control
played wave length. They're all encoded in the same fashion as the same info in Apple IIGS
instruments (More info [[AGI/Specifications/Sound#MIDI_sequences | here]]).
Committed the Apple IIGS AGI sample loading code to the trunk
(/scummvm/trunk/engines/agi/sound.cpp: diff to
[http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/engines/agi/sound.cpp?r1=27024&r2=28404&sortby=date r28404] and
[http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/engines/agi/sound.cpp?r1=28404&r2=28405&sortby=date r28405])
== 2007-08-03 (Friday) - Figured out most of the missing parts of the Apple IIGS sample header ==
Finally figured out most of the missing parts of the Apple IIGS sample header (A not-so-pretty
[http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/engines/agi/sound.cpp?r1=28405&r2=28432&diff_format=l diff].
Look at struct IIgsSampleHeader). I had pondered whether there was some kind of an envelope in the header...
and there is! It's actually identical to a part of the Apple IIGS instrument header. Making
that connection was the key. Looking at the sample headers' histogram in Open Office also helped
(I had made a Python program for gathering the data and outputting it as comma separated values
to a text file. Open Office can import those .CSV-files so it's easy to read the data in).
Also as a side thing I extracted the Apple IIGS AGI arrow cursor data from a screenshot and
committed it to the trunk
([http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/engines/agi/graphics.cpp?r1=28387&r2=28436 Diff]).
Here's what the Apple IIGS AGI arrow cursor looks like on a blue background:
[[Image:AppleIIgs-AGI-arrow_cursor-upscale_x10.png|frame|none|Apple IIGS AGI arrow cursor]]
On a different note I watched Assembly 2007's Oldskool Demo competition online during the night.
Vic-20, Atari 2600 and NES demos, whee :-). The NES demo had nice speech effects for the credits.
If you're interested be sure to check out the 64kB intro compo and the main demo compo today using
[http://www.assemblytv.net/2007/stream-en Assembly TV].
== 2007-08-04 (Saturday) - A couple of compilation fixes ==
Carch on #scummvm told of a couple of compilation problems that
ScummVM's current trunk has on on Windows (VS2003), Xbox (VS2003) and Xbox 360
(VS2005). We investigated the problems together and I committed the
fixes to the trunk ([http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/engines/agi/sound.cpp?r1=28445&r2=28446&sortby=date Here] and
[http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/engines/kyra/script.cpp?r1=28297&r2=28447&sortby=date here]).
In Kyra's code an object wasn't converted automatically to a boolean value even though it
had an operator bool defined so I added an explicit bool conversion and that fixed the problem.
In the AGI code there was a problem with automatic selection of the wanted version of the
pow-function. So I replaced the offending pow-function call with a constant value as it
actually was calculating a constant and not a variable and it worked. Carch also gave another
way to fix the problem and that was to replace the pow(2, 1/12.0) call with a pow(2.0, 1/12.0)
call. That way the compiler knew to choose the pow(double, double) version of the pow-function.
== 2007-08-06 (Monday) - Mostly a holiday ==
Didn't sleep much last night (About 3,5h or so) and my sister came to visit
with her children. Played with my niece, took an evening nap, ate, watched
Michio Kaku's Time-documentary's 4th part and also Simpsons etc. So this
was mostly a holiday.
== 2007-08-07 (Tuesday) - Working on Apple IIGS instrument loading ==
Worked on Apple IIGS instrument loading code for ScummVM.
== 2007-08-08 (Wednesday) - Some more work on the Apple IIGS instrument loading ==
Worked some more on the Apple IIGS instrument and wave file loading code
(Here's today's tiny [http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/engines/agi/sound.cpp?r1=28501&r2=28505 commit]).
== 2007-08-09 (Thursday) - Committed Apple IIGS instrument and wave file loading code ==
Committed the Apple IIGS instrument and wave file loading code to the trunk.
Diffs:
* Small commits:
** [http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/engines/agi/sound.cpp?r1=28505&r2=28506 Removed old loadInstruments()]
** [http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/engines/agi/sound.cpp?r1=28506&r2=28507 Brought back and changed some variables from inside a #if 0 ... #endif]
* The main bulk of code:
** Added Apple IIGS instruments and wave file loading. (Apple IIGS music playing is broken at the moment)
*** [http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/engines/agi/sound.cpp?r1=28507&r2=28508 Code]
*** [http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/engines/agi/sound.h?r1=27024&r2=28508 Header definitions]
Also learned that the command line tool svn doesn't convert "\n" to a newline (I gave a commit log with the -m parameter
to the svn-tool with a "\n" in it. It didn't convert it at all but just copied it as it is to the commit log).
== 2007-08-10 (Friday) - True sample size calculation and taking variables apart ==
Worked on fixing the Apple IIGS samples' sizes as they can be smaller in reality
than what's saved in the sample headers. It can be so because a zero in the sample
data stream will end the sample prematurely (That's something the Apple IIGS's
sound chip [http://en.wikipedia.org/wiki/Apple_IIGS#Audio_features Ensoniq ES5503 DOC] did).
Also decided to be more free with how I save data in the memory, that is I decided to take
apart some bit field variables read from files and save them in the memory as multiple
variables etc. So the data should now be easier to use.
== 2007-08-13 (Monday) - Restructured some of the Apple IIGS sound code etc ==
Restructured some of the Apple IIGS sound code (Put functions inside structs etc).
Realized when talking with Sev that the code submission and evaluation deadline
is next monday, on the 20th. That hadn't really sunk in yet in my mind so this means
this week's going to include lots of ScummVM hacking :).
== 2007-08-14 (Tuesday) - General Apple IIGS sound hacking #1 ==
Worked on the Apple IIGS sound code.
== 2007-08-15 (Wednesday) - General Apple IIGS sound hacking #2 ==
More work on the Apple IIGS sound code.
== 2007-08-16 (Thursday) - Inspecting Apple IIGS MIDI sound resources ==
Played around with the Apple IIGS AGI midi sound resources. Yep, they're
standard MIDI files with a 16-bit little endian 0x0002 header. Sometimes they
start with 0xFC (Stop sequence) right after the header with no encoded delta-time
before the command. And sometimes they end by simply exhausting the midi stream's
length and not giving a 0xFC (Although it might be just that I'm not parsing the
files 100% correctly yet and that's what's making it happen). Also some of the
midi streams seem to have additional data after the first encountered 0xFC. I
looked at the additional trailing data from some of the files and at a first
glance it seems they're full of commands for centering the pitch wheel on different
channels, setting some default values for different controllers or something like that.
Here are some statistics about the Apple IIGS AGI midi sound resources I tested:
* Used commands in the Apple IIGS AGI midi resources (Approximate counts):
** 0x80: 00064488 "Note off" (Varying parameters)
** 0x90: 00065516 "Note on" (Varying parameters)
** 0xB0: 00006252 "Controller" (Varying parameters)
** 0xC0: 00001574 "Program Change" (Varying parameters)
** 0xE0: 00000146 "Pitch Wheel" (Only used with parameter 0x2000 i.e. wheel center)
** 0xFC: 00000271 "Stop sequence" (No parameters for this, ends the stream)
(Update on 2007-08-30: The numbers given above aren't totally correct as
I parsed delta-time as a variable length quantity - rather than a single byte
as it seems to be in these files - when I generated these statistics).
== 2007-08-17 (Friday) - First Apple IIGS sample playing! ==
Got an experimental and not-pretty sound mixing code to run and heard the first
Apple IIGS sample playing at a near reasonable pitch too :-). Whee! Getting something
concrete done raises the spirit! Had some red wine and blue cheese for
celebration :-).
== 2007-08-18 (Saturday) - More Apple IIGS sound hacking ==
It seems samples aren't looped if a zero in the sample is encountered. So even
if the mode for the sample is set to looping but a zero is encountered in the
sample data the sample will not loop, it will just end.
Whee! Seems like I got most of the samples to play at a correct pitch now!
BTW as a random thought King's Quest III's Apple IIGS version doesn't have
speed settings (slow/normal/fast/fastest) at all, so it can be a pain to play
it using ScummVM. Might have to force some speed settings to the menus...
Played around with the envelopes and as I found out after little testing that
the relative pitch and envelope increment values are 16-bit little endian
values, not 16-bit big endian as I had assumed before, the enveloping started
to sound more authentic like.
== 2007-08-19 (Sunday) - Some more Apple IIGS MIDI hacking ==
=== Broken MIDI files ===
Seems like King's Quest II's starting song (Greensleeves, sound resource 0)
isn't parsed right. Here's its start:
<pre>
00000000          02 -- 02 00 means that it's an Apple IIGS midi sequence
00000001 00 00 c0 16 -- Then some program changes (command 0xC?)
00000005 00 c8 20 00 -- ...
00000009 c2 14 00 c3 -- ...
0000000d 22 00 c4 22 -- ...
00000011 00 c5 22 00 -- ...
00000015 c6 2a 00 c7 -- ...
00000019 26 00 c1 14 -- ...
0000001d 01 b0 07 69 -- Delta-time 01: controller 7, chan 0, val 0x69
00000021 00 b8 07 76 -- Delta-time 00: controller 7, chan 8, val 0x76
00000025 00 b2 07 6d -- Delta-time 00: controller 7, chan 2, val 0x6d
00000029 00 b3 07 7c -- Delta-time 00: controller 7, chan 3, val 0x7c
0000002d 00 b4 07 7c -- Delta-time 00: controller 7, chan 4, val 0x7c
00000031 00 b5 07 7c -- Delta-time 00: controller 7, chan 5, val 0x7c
00000035 00 b6 07 76 -- Delta-time 00: controller 7, chan 6, val 0x76
00000039 00 b7 07 76 -- Delta-time 00: controller 7, chan 7, val 0x76
0000003d 00 b1 07 6a -- Delta-time 00: controller 7, chan 1, val 0x6a
00000041 85 90 40 26 -- BUT HERE IT BREAKS DOWN at 0x41 with byte 0x85
00000045 00 93 4c 26 -- Here are really note on commands (Parsed as controller commands)!
</pre>
So at 0x41 with byte 0x85 it's taken as a first byte of a variable
length quantity (Delta-time here) that's more than one byte long because
the value is over 0x80! After that the data is parsed as controller
commands which it really isn't, it's note on and note off commands.
Why is this this way? What to do? Some bandaid fixing maybe?-)
We'll see...
More breakage:
King's Quest IV's MIDI sound resource 14:
<pre>
00000021 00 b7 07 5a
00000025 d3 96 56 47 -- Here at 0x25 with 0xd3 again the same kind of breakage
00000029 00 97 4a 47
</pre>
King's Quest IV's MIDI sound resource 39:
<pre>
0000001a 00 b5 07 63
0000001e 99 95 40 1d  -- Here at 0x1e with 0x99 again the same kind of breakage
00000022 11 93 40 44
</pre>
King's Quest IV's MIDI sound resource 46:
<pre>
0000003d 00 b8 07 73
00000041 ea 97 43 7c -- Here at 0x41 with 0xea again the same kind of breakage
00000045 00 98 43 7c
</pre>
King's Quest IV's MIDI sound resource 105:
<pre>
0000001a 00 b7 07 71
0000001e ec 94 3e 23 -- Here at 0x1e with 0xec again the same kind of breakage
00000022 00 95 4a 23
</pre>
King's Quest IV's MIDI sound resource 109:
<pre>
00000017 00 b3 07 78
0000001b 93 93 31 4e -- Here at 0x1b with 0x93 again the same kind of breakage
0000001f 02 91 59 52
</pre>
King's Quest IV's MIDI sound resource 207:
<pre>
0000001a 00 b5 00 78
0000001e 8a 95 3e 54 -- Here at 0x1e with 0x8a again the same kind of breakage
00000022 03 40 41 05
</pre>
Mixed-Up Mother Goose's MIDI sound resource 7:
<pre>
0000003d 00 b8 07 73
00000041 95 92 43 6f -- Here at 0x41 with 0x95 again the same kind of breakage
00000045 00 95 4f 66
</pre>
Mixed-Up Mother Goose's MIDI sound resource 37:
<pre>
0000003d 00 b8 07 72
00000041 96 92 47 76 -- Here at 0x41 with 0x96 again the same kind of breakage
00000045 00 95 53 73
</pre>
=== Possible explanation for the broken MIDI files ===
It might just be that Apple IIGS AGI MIDI files don't use a variable
length quantity for the delta-time but always use a single byte delta-time
which *can* be >= 0x80! Investigating... (If this is so then it's a non-standard
behaviour for a MIDI file)
Update! Okay, so it seems these MIDI files don't use variable length quantities
for delta-time. Delta-time is always one single byte even if it might be >= 0x80.
But! That delta-time byte also acts as a shorthand for commands like 0xFC
(Stop sequence) or 0xF8 (Timer sync).
So let's read a single byte from the stream. If it's 0xFC it stops the
sequence right there. If it's 0xF8 we can probably just jump over it as we
probably don't need it. Otherwise you use the byte's value as a delta-time
and then you read the command byte, parameters etc normally (Running status
is also used). At least this is my current theory based on experiments with
a Python program I wrote for parsing these MIDI files.
I checked some files and yes it really does seem we do need to check for end
of sequence (0xFC) before reading the delta-time as some files do use 0xFC
where the delta-time would be.
=== I'm going bughunting... be vevy vevy quiet! ===
I wasn't planning on going bughunting but as I tried to submit
my MIDI parsing/stepping-through code into SVN I found out that
sound didn't work with AGI in the SVN. Possibly Fingolfin inadvertently
broke it with the OOficiation/clean-up -commits to the AGI's sound code
or made the bug somehow come up more easily (At least AFAIK it
didn't crash like that before ;-)). Well, in the wee hours I disgruntently
tried to fix the bug and at last I succeeded (Here's the [http://scummvm.svn.sourceforge.net/viewvc/scummvm/scummvm/trunk/engines/agi/sound.cpp?r1=28671&r2=28672&sortby=date diff]
for the fix. The crash was happening because the PCjr sound mixing code tried to use uninitialized values (e.g. phase, ins) when mixSound was called before anything was playing).
Come to think of it I'm not really sure how it has been able to *not* crash before :).
After fixing the crashing bug I got to the point where I could commit
the MIDI parsing/stepping-through code into the SVN. Whee, it's not
perfect (Speed's probably off), it doesn't use the MIDI classes yet etc,
but it steps through the MIDI files (That aren't totally standard) hopefully
quite correctly :).
== 2007-08-20 (Monday) - Juryrigged Apple IIGS MIDI output for first sound testing! ==
Juryrigged the Apple IIGS MIDI parsing code to fill the sound buffer with a sine wave
when encountering a Note On -command in the MIDI stream (Using the Note On -command's
note frequency data to adjust the sine wave's frequency too). What sounds I got :-)
heh, but at least I recognized the Greensleeves -theme from King's Quest II's intro ;).
Hopefully the wiki's upload file functionality will be working again in the near
future so I could upload a sample of the buzzes I saved from the testings :).
Later today I thought about the mixing stuff and I'm thinking it quite probable that
we'll hear some real samples soon! (Not possibly the correct samples yet because
the Program Change -command's parameter isn't deciphered yet so I'm not certain what
instrument should go where).
== 2007-08-21 (Tuesday) - Oscillator mode comparison etc ==
Compared the used oscillator modes in the Apple IIGS AGI games from
both the instruments and samples:
I found these used combinations of modes:
* Both waves (A and B) in an oscillator use the same mode:
** Oneshot (Used very much by samples and by a few instruments (Probably drums, I presume))
** Loop (Used quite much by samples, very much by instruments)
** Loop + Halt (The only thing using this is the unique instrument that has four oscillators)
** Swap (The only thing using this is the unique instrument that has four oscillators)
* Waves A and B in an oscillator use different modes:
** Oneshot / Loop + Halt (Used quite much by samples and by a few instruments)
** Loop / Loop + Halt (The only thing using this is Police Quest I's sample 12)
** Swap / Swap + Halt (The only thing using this is Gold Rush's sample 60)
This means I can ignore the Sync (Amplitude Modulation) oscillator mode for now
as it's not used by at least the Apple IIGS AGI games I tested. And ignoring the
Swap oscillator mode isn't going to hurt much *if* the one unique instrument that
has four oscillators isn't used much (I don't know how much it's used yet though,
so there's still a bit of a risk). Oh, and I do presume the Gold Rush's sample 60
isn't used very widely :-) (It's a sound of a horse's hoof hitting pavement).
== 2007-08-22 (Wednesday) - My birthday! ==
This is my birthday! Yay! Spent most of the day with my family, played with
my niece (We were a bunny family and we were scared of the wolves around our
house so we called the police who came and locked the wolves into prison and
shot the ones that tried to run away :-)), had some coffee and cake, went
to sauna and watched Zorba The Greek during the late evening.
Oh and I discovered/realized that at least Apple IIGS King's Quest I's volume
files are not encrypted. So I can just go and write new MIDI codes straight
into the files and run the game through an emulator to try to hear what
program change corresponds to what instrument. Whee :-) This is good.
== 2007-08-23 (Thursday) - Investigating MIDI controller commands and instruments ==
Used Python to write test MIDI data into Apple IIGS King's Quest I's disk image
(Straight onto the MIDI sound resource number 0 i.e. the intro song) and ran it through MESS
and KEGS32. It seems you can use just about any controller on a channel and all
it does is change its volume :-). So controller 0, 7, 64, whatever, they seem to
be only for changing volume (Haven't done extensive testing yet, so it is possible
they may act differently in some situations).
Wrote some test MIDI data to see what the program changes do. They seem to change
the instrument played on a channel, that's for sure, but I'm not yet sure of the
mapping between the program change parameter and the instrument number.
Also tried varying the velocity of note on and note off commands (Used program 36
on channel 0). It didn't do jack :). But! As the velocity information *is* there,
it might be used even if Apple IIGS AGI didn't use it (There's of course the possibility
that the emulators just mess it up somehow, but MESS should be quite good, eh?-)).
So we might even hear more articulate versions of the songs using ScummVM if we'll
use the velocity info! We shall see...
== 2007-08-28 (Tuesday) - Reverse engineering the program change to instrument mapping ==
Been trying to reverse engineer the Apple IIGS AGI MIDI files' program change command's
parameter value to instrument number mapping recently. Tried a few approaches that didn't work
but came up with a way that works quite well. Here's the preliminary mapping from
program numbers to instrument numbers (Instrument number 6 seems to be mostly used to
mean an "undefined instrument" or a "not used instrument"):
=== Preliminary MIDI program change to Apple IIGS AGI instrument mapping ===
Programs 0-9:
* Instruments: 21, 22, 24, 25, 23, 26, 6, 6, 6, 6
Programs 10-19:
* Instruments: 7, 9, 12, 8, 13, 11, 17, 10, 6, 6
Programs 20-29:
* Instruments: 19, 18, 20, 14, 16, 6, 6, 6, 6, 6
Programs 30-39:
* Instruments: 0, 1, 2, 4, 3, 5, 17, 2, 2, 2
** The trailing 2's are probably somehow modified so they don't sound identical
Programs 40-49:
* Instruments: 27, 15, 15, 27, 6, 6, 6, 6, 6, 6
I'd venture that the used instruments in different base 10
parts (First ten programs, second ten programs etc) are
different instrument categories (e.g. programs 20-29 are
for drums). Haven't yet tested this but it would seem logical.
Oh and this preliminary mapping is for the newer Apple IIGS AGI instrument set (i.e.
used by all other test subjects except Space Quest I).
== 2007-08-29 (Wednesday) - Program changes comparison etc ==
Here's some info about the Apple IIGS AGI MIDI files' program changes:
Older Apple IIGS AGI instrument set: (Space Quest I, AGI v1.002):
* Used programs: [0, 1, 2, 4, 5, 10, 16, 20, 22, 32, 33, 36, 38, 39, 40]
* Unused programs (Range 0-43): [3, 6, 7, 8, 9, 11, 12, 13, 14, 15, 17, 18, 19, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 34, 35, 37, 41, 42, 43]
Newer Apple IIGS AGI instrument set: (All others together, AGI v1.003+):
* Used programs: [0, 1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15, 16, 20, 21, 22, 23, 24, 29, 30, 31, 32, 33, 34, 35, 36, 38, 39, 40, 41, 42, 43]
* Unused programs (Range 0-43): [6, 7, 8, 9, 17, 18, 19, 25, 26, 27, 28, 37]
Not using programs 6-9 and 18-19 makes sense because they use
the instrument 6 that seems and sounds somewhat weird.
Not using programs 25-29 would make sense for the same reason
but it seems program 29 is used... by only Manhunter I's MIDI
sound resources 116 and 142! So it *might* be only a fluke but
not necessarily so.
Programs 32 and 37-39 seem to use the same instrument but still
sound different. Although program 37 seems not to be used
at all there are still programs 32, 38 and 39 to look into.
Maybe some additional tweaking somewhere else than in the
instrument data?
Programs 40 and 43 use the same samples and probably the same instrument.
Same goes for programs 41 and 42. Gotta investigate them more closely too...
As a sidenote program 17 seems ok but for some reason it seems not to be used
at all. Maybe just not a particularly popular instrument?-)
== 2007-08-30 (Thursday) - SIERRASTANDARD investigation etc ==
The Apple IIGS AGI uses a file named SIERRASTANDARD that holds
the sample data used by the instruments. It's 65536 bytes in size,
it holds 8-bit unsigned sample data and all the different samples
start on 256 byte boundaries. None of the SIERRASTANDARD files I've
tested have zeroes in them (A zero would mark a premature end of a sample).
After some investigation (Looking at the file rawly imported into Audacity) etc
here's some info on it (This info applies directly to the newer SIERRASTANDARD
file used with Apple IIGS AGI v1.003+. There are some little differences in
the older SIERRASTANDARD file that's used at least with Space Quest I (AGI v1.002)):
=== Samples in the newer SIERRASTANDARD file ===
* Number of samples (Not all unique!):
** 34
* Sample redundancy (May be incomplete):
** Samples 18 and 30 are identical (A base drum)
** Samples 21 and 31 are identical (Sounds like a drum stick hit)
** Samples 24 and 32 are identical (Sounds like hihat)
** Samples 27 and 33 are identical (Sounds quite like a shaman drum)
* "Dummy" samples
** Sample 4 is full of byte 0x50 (i.e. about -0.38 if amplitude is normalized to range [-1, +1])
* Unused samples (i.e. not used by the instrument data. May be incomplete):
** None of the instruments in either the older or the newer instrument set use samples 29-33
*** This means we could theoretically ditch the last 16KiB of the SIERRASTANDARD file
** None of the instruments in the older instrument set use samples 2-4
** None of the instruments in the newer instrument set use sample 4
* Sample sizes log2 (2**x will give the true sample size):
** sampleSizesLog2 = [10, 10, 10, 9, 9, 10, 10, 10, 10, 10, 10, 11, 10, 10, 10, 10, 10, 10, 11, 10, 10, 11, 10, 10, 11, 10, 10, 11, 14, 13, 11, 11, 11, 11]
* Sample sizes (This table can be calculated from the sample sizes log2):
** sampleSizes = [1024, 1024, 1024, 512, 512, 1024, 1024, 1024, 1024, 1024, 1024, 2048, 1024, 1024, 1024, 1024, 1024, 1024, 2048, 1024, 1024, 2048, 1024, 1024, 2048, 1024, 1024, 2048, 16384, 8192, 2048, 2048, 2048, 2048]
*** Way to calculate this with Python: sampleSizes = map(lambda x: 2**x, sampleSizesLog2)
*** Note that sum(sampleSizes) should always be 65536 (The size of SIERRASTANDARD)
* Sample positions (This table can be calculated from the sample sizes):
** samplePos = [0, 1024, 2048, 3072, 3584, 4096, 5120, 6144, 7168, 8192, 9216, 10240, 12288, 13312, 14336, 15360, 16384, 17408, 18432, 20480, 21504, 22528, 24576, 25600, 26624, 28672, 29696, 30720, 32768, 49152, 57344, 59392, 61440, 63488]
*** Way to calculate this with Python:  samplePos = [sum(sampleSizes[:end]) for end in xrange(len(sampleSizes))]
=== Differences between the older SIERRASTANDARD and the newer SIERRASTANDARD file ===
Here are all the differences between the older and the newer SIERRASTANDARD file:
* Sample 2 (Offsets 2048-3071) differs between SIERRASTANDARD versions
** Sample data
*** The older version of sample 2 starts with some real sample data but a bit over half of it is completely silent (i.e. centerline i.e. byte 0x80)
*** Newer version of sample 2 contains real sample data
** Instrument usage
*** None of the instruments of the older instrument set use sample 2
*** Instruments 19 and 20 of the newer instrument set use sample 2
* Sample 3 (Offsets 3072-3583) differs between SIERRASTANDARD versions
** Sample data
*** The older version of sample 3 is full of byte 0x50
*** The newer version of sample 3 contains real sample data
** Instrument usage
*** None of the instruments of the older instrument set use sample 3
*** Instrument 4 of the newer instrument set uses sample 3
* Sample 17 (Offsets 17408-18431) differs between SIERRASTANDARD versions
** Sample data
*** Both versions of SIERRASTANDARD use real sample data here
*** Newer version's sample has a higher pitch than the old version and the wave looks more triangle like
** Instrument usage
*** Instruments 5 and 18 of the older instrument set uses this sample
*** Instrument 6 of the newer instrument set uses this sample
* Sample 27 (Offsets 30720-32767) differs between SIERRASTANDARD versions
** Sample data
*** The older version of sample 27 consists mostly of silence (Byte 0x80) followed by some 0x0F
*** The newer version uses real sample data here (Identical to the last sample i.e. sample 33)
** Instrument usage
*** Instruments 5 and 23 of the older instrument set use this sample
*** Instruments 6 and 25 of the newer instrument set use this sample
== 2007-12-11 (Tuesday) - End of GSoC 2007 project diary ==
I thought I'd add a clarifying end note to my project diary. I'm not going to update the
diary anymore but I leave it here for archival purposes. It might prove an interesting or even
a useful read for someone else applying for GSoC in ScummVM. It was a good ride...
417

edits

Navigation menu