https://segaretro.org/api.php?action=feedcontributions&user=Clownacy&feedformat=atomSega Retro - User contributions [en]2024-03-29T10:02:04ZUser contributionsMediaWiki 1.33.4https://segaretro.org/index.php?title=RF5C164&diff=968562RF5C1642024-03-20T15:12:07Z<p>Clownacy: Created a basic stub that links to some documentation.</p>
<hr />
<div>{{stub}}<br />
{{ICBob<br />
| image=<br />
| title=<br />
| designer=[[Ricoh]]<br />
| date=<br />
}}<br />
<br />
The '''RF5C164''' is a sound synthesiser integrated circuit made by [[Ricoh]]. It is capable of playing 8 streams of 8-bit PCM audio simultaneously. It is used by the [[Sega Mega CD]].<br />
<br />
==Documentation==<br />
<gallery><br />
MCDHardware_Manual_PCM_Sound_Source.pdf|''Mega CD Hardware Manual - PCM Sound Source''<br />
RF5C68A.pdf|Manual for the RF5C68A, which is similar (but not identical) to the RF5C164. This manual contains some information which is not found in the other.<br />
</gallery></div>Clownacyhttps://segaretro.org/index.php?title=File:RF5C68A.pdf&diff=968560File:RF5C68A.pdf2024-03-20T15:09:16Z<p>Clownacy: Official manual for the Ricoh RF5C68A, which is similar (though not identical) to the RF5C164. This manual contains information which is not found in the RF5C164's manual.
Category:Hardware documentation files</p>
<hr />
<div>== Summary ==<br />
Official manual for the [[Ricoh]] RF5C68A, which is similar (though not identical) to the [[RF5C164]]. This manual contains information which is not found in the RF5C164's manual.<br />
<br />
[[Category:Hardware documentation files]]</div>Clownacyhttps://segaretro.org/index.php?title=File:MCDHardware_Manual_PCM_Sound_Source.pdf&diff=968559File:MCDHardware Manual PCM Sound Source.pdf2024-03-20T14:45:19Z<p>Clownacy: Clownacy uploaded a new version of File:MCDHardware Manual PCM Sound Source.pdf</p>
<hr />
<div>[[Category:Mega-CD official documentation files]]</div>Clownacyhttps://segaretro.org/index.php?title=SMPS&diff=965465SMPS2024-03-06T16:13:46Z<p>Clownacy: Added a section listing developers that were credited in SMPS's source code.</p>
<hr />
<div>'''Sample Music Playback System''' ('''SMPS''') is the common name of a family of audio playback engines (or "drivers") and storage formats used by various [[Sega]] consoles (including the [[Sega Mega Drive]], [[Sega Mega-CD]], [[Sega 32X]], [[Sega Master System]], [[Sega Game Gear]], and [[Sega Pico]]). "SMPS" is thought to be a colloquial term - there is no evidence to suggest this was the naming scheme of any official drivers, but is the most widely accepted name for the system.<br />
<br />
Like other sound drivers, SMPS was designed as a means of processing audio information, allowing a console's CPU to communicate with sound chips on the board and create audible sound (i.e. "driving" the sound). It is usually associated with first-party Japanese Mega Drive games (where it was most predominantly used) - analogous to [[Sega of America]]'s use of the [[GEMS]] driver, and began appearing in games from the late 1980s until the aforementioned consoles bowed out of the market.<br />
<br />
By sharing drivers between games, developers could create tools to quickly produce audio, and it allows for music and sound effects to be more easily ported between games.<br />
<br />
==Variants==<br />
===Mega Drive and 32X===<br />
Mega Drive (and by extension, 32X) developers had a choice of which processor to run SMPS on; the 16-bit [[68000]], or the 8-bit [[Z80]]. The driver variants are known as '''SMPS 68000''' and '''SMPS Z80''' respectively.<br />
<br />
Some developers, such as [[Treasure]], chose to modify the driver, effectively making their own variants. Individual games such as ''[[Ristar]]'' also have their own modified drivers.<br />
<br />
====Source code====<br />
The source code to both SMPS-68000 and SMPS-Z80 was found and released by Hidden Palace in 2020[https://hiddenpalace.org/News/Sega_of_Japan_Sound_Documents_and_Source_Code]. The versions of the two drivers appear to be SMPS-68000 Type 1B and SMPS-Z80 Type 2 DAC.<br />
<br />
{{Download<br />
| title=SMPS-68000 source code<br />
| file=SMPS-68000_source_code.zip<br />
}}<br />
{{Download<br />
| title=SMPS-Z80 source code<br />
| file=SMPS-Z80_source_code.zip<br />
}}<br />
<br />
====Games which use SMPS 68000====<br />
=====Mega Drive=====<br />
{{SoundDriverList|SMPS 68000|MD}}<br />
<br />
=====32X=====<br />
{{SoundDriverList|SMPS 68000|32X}}<br />
<br />
====Games which use SMPS Z80====<br />
=====Mega Drive=====<br />
{{SoundDriverList|SMPS Z80|MD}}<br />
<br />
=====32X=====<br />
{{SoundDriverList|SMPS Z80|32X}}<br />
<br />
===Mega-CD===<br />
'''SMPS-PCM''' is variant of SMPS-68000 designed to work on the Mega-CD's second 68000 processor, giving it access to the system's [[RF5C164]] PCM chip.<br />
<br />
===Master System and Game Gear===<br />
SMPS drivers designed to work on the Z80 processors of the Master System and Game Gear were also produced. These tap into the two consoles' [[SN76489]] chip.<br />
<br />
===Pico===<br />
'''SMPS-Pico''' is a variant of SMPS-68000 that targets the Sega Pico. It plays audio using the [[SN76489]] and the Pico-specific [[UPD7759]] chip.<br />
<br />
The source code to this particular SMPS variant was released on AssemblerGames some time around 2016.<br />
<br />
{{Download<br />
| title=Sega Pico Dev Tools<br />
| file=SEGA_Pico_dev_tools.zip<br />
}}<br />
<br />
==Naming==<br />
The 'true' name of SMPS remains a subject of debate. Analysis of the source code reveals various possible names:<br />
<br />
{| class="prettytable" style="width:auto;"<br />
! Name !! Usage<br />
|-<br />
| Sound<br />
| Appears frequently in documentation (m5_edit.jxw, ver11.doc, etc.). In the source code, this is the name of the label that marks the driver's entry point (m5cnt13.src, mdcnt11.asm).<br />
|-<br />
| Sound-Sorce<br />
| Appears in the header at the top of SMPS-Z80's source code files. Included with the source code is a [[wikipedia:sed|sed]] script that replaces the instances of this name with a parameter that is labelled 'game name'. This script was seemingly used on a handful of files, replacing 'Sound-Sorce' with 'MODEM_BOOT_ROM' and 'DICK_TRACY'.<br />
|-<br />
| Sound-Source<br />
| Appears in the header at the top of SMPS-68000's and SMPS-Pico's source code files. It is also the name used by some developers who had used SMPS back in the 90s[https://web.archive.org/web/20191006015702/https://twitter.com/Hikoshi_H/status/1180661206253596672][https://web.archive.org/web/20190920174036/https://twitter.com/Hikoshi_H/status/1169707879164608513][https://web.archive.org/web/20200719143541/https://twitter.com/Mazin__/status/105869176442331136]. Included with the source code is a sed script that replaces the instances of this name with a parameter that is labelled 'game name'.<br />
|-<br />
| Sound-Sample<br />
| Written on the SMPS-68000 and SMPS-Z80 source code's floppy disks. The SMPS-68000 source code has a Batch script (fmk.bat) that uses the aforementioned sed script to replace 'Sound-Source' with 'Sound-Sample'.<br />
|-<br />
| EASYSND<br />
| The name of the zip file that holds another zip file which contains the SMPS-Pico source code.<br />
|-<br />
| PICOSND<br />
| The name of the zip file which contains the SMPS-Pico source code. Also appears in various filenames and build scripts.<br />
|-<br />
| The PICO sound driver<br />
| Used by SMPS-Pico's GENERIC.MAK and PICOSND.MAK files.<br />
|}<br />
<br />
==Developers==<br />
The names of several developers appear in SMPS' source code:<br />
{| class="prettytable" style="width:auto;"<br />
! Name !! Role !! Source<br />
|-<br />
| [[Tokuhiko Uwabo]] || Maintainer of SMPS-Z80. || The header of each source code file. Also mentioned by his Japanese name in the 'm5_bord.jxw' document.<br />
|-<br />
| [[Hiroshi Kubota]] || Maintainer of SMPS-68000. || The header of each source code file. Also mentioned by his Japanese name in the 'readme.txt' document.<br />
|-<br />
| "M.Nagao" (presumably [[Masayuki Nagao]]) || Maintainer of SMPS-Pico. || The header of each source code file.<br />
|-<br />
| [[Ken Chao]] || 'Cleaned-up' the SMPS-Pico source code for use by U.S. and European developers. || The 'README.1ST' document.<br />
|}<br />
<br />
==Technical details==<br />
*[[SMPS/Headers|Headers]]<br />
*[[SMPS/Voices and samples|Voices and samples]]<br />
*[[SMPS/Song data|Song data]]<br />
<br />
==Tools==<br />
*[[xm4smps]]<br />
*[[xm3smps/oerg]] (official improved branch of [[xm3smps]])<br />
<br />
== External links ==<br />
*[http://gdri.smspower.org/wiki/index.php/Mega_Drive/Genesis_Sound_Engine_List A list of the sound engines used on the Mega Drive]<br />
<br />
==References==<br />
<references /><br />
[[Category:Mega Drive sound drivers]]<br />
[[Category:SMPS]]</div>Clownacyhttps://segaretro.org/index.php?title=Yoshiaki_Kashima&diff=965453Yoshiaki Kashima2024-03-06T15:30:31Z<p>Clownacy: Remove incorrect information about Sonic 3's driver being based on Sonic 2's.</p>
<hr />
<div>{{PersonBob<br />
| image=YoshiakiKashima.jpeg<br />
| birthplace=[[wikipedia:Kōchi, Japan|Kōchi, Japan]]{{ref|https://web.archive.org/web/20040807171523/http://www.milkland.jp/office.html}}<br />
| dob=19xx-01-25{{ref|https://web.archive.org/web/20040807171523/http://www.milkland.jp/office.html}}<br />
| dod=<br />
| employment={{Employment<br />
| company=[[Sega Enterprises, Ltd.|Sega Enterprises]]<br />
| divisions=[[Sega Digital Media|Sega Digital Media Planning Dept.]]{{intref|D-2}}<br />
}}<br />
| role=Musician, Programmer<br />
| education=<br />
}}<br />
{{sub-stub}}'''{{PAGENAME}}''' (香嶋 良昭) is a former sound programmer for many [[Sega]] games. He created the modified [[SMPS Z80]] sound driver that was used by ''[[Sonic the Hedgehog 3]]'', ''[[Sonic & Knuckles]]'', and ''[[Sonic 3D: Flickies' Island]]'', as well as the one that was used by ''[[Chaotix]]''. He left the company sometime around 1999-2000, and later found work with Sexy Death Entertainment, [[Banpresto]], and Sound AMS.<br />
<br />
He is better known by his alias, '''Milpo''' (みるぽ).<br />
<br />
==Production history==<br />
{{ProductionHistory|Yoshiaki Kashima|Y.Kashima|Kashima Yoshiaki|Milpo|香嶋 良昭}}<br />
<br />
[[Category:Uncredited role]]<br />
[[Category:Use ProductionHistory template]]<br />
* ''[[Sonic 3D: Flickies' Island]]'' (Mega Drive Version) (1996) [NOTE: Sound Driver]<br />
* ''[[Radio DC]]'' (CD) (1999) (as '''Yoshi K.''')<br />
* 16 Polyphonic Ringtones (docomo/J-Phone) (2001) — Production (Sega Music Networks)<br />
* 40 Polyphonic Ringtones (docomo/J-Phone) (2002) — Production (Sega Music Networks)<br />
<br />
==Song credits==<br />
{{mainArticle|{{PAGENAME}}/Song credits}}<br />
[[Category:Old song credits]]<br />
{{multicol|<br />
===''[[Seima Densetsu 3x3 Eyes]]''===<br />
* Dark Foment -Venares- — Music<br />
* Setting Off — Music<br />
* Kindhearted — Music<br />
* Ancient Great Wizard - Venares — Music<br />
* Sacred Strength — Music<br />
* Holy Ground — Music<br />
* I Will Treat You Only as a Human Being... — Music<br />
* Legend of the Holy Demon (Main Theme) — Music<br />
* City of Romantic Stories - Hong Kong — Music & Arrangement<br />
* China — Music & Arrangement<br />
* Beast Thieves Den — Music & Arrangement<br />
* Tibet — Music & Arrangement<br />
* Linde Republic — Music & Arrangement<br />
* Death-Dance-Disco — Music & Arrangement<br />
* Yakumo's Theme — Music & Arrangement<br />
* Pai's Theme — Music & Arrangement<br />
* Long's Theme — Music & Arrangement<br />
* Gupta's Theme — Music & Arrangement<br />
* Haan's Theme — Music & Arrangement<br />
* Ling Ling's Theme — Music & Arrangement<br />
* Meixing's Theme — Music & Arrangement<br />
* Battle-1 — Music & Arrangement<br />
* Last Battle — Music & Arrangement<br />
<br />
===''[[Sonic the Hedgehog 3]]''===<br />
* Special Stage — Music & Arrangement<br />
<br />
===''[[Radio DC]]''===<br />
* Switch Again — Hero Voice<br />
}}<br />
<br />
==External links==<br />
* [http://milkland.jp/ Official website]<br />
<br />
==References==<br />
<references/></div>Clownacyhttps://segaretro.org/index.php?title=Nintendo&diff=965251Nintendo2024-03-06T00:44:49Z<p>Clownacy: /* Video game platforms */ Spell 'directly' correctly.</p>
<hr />
<div>{{CompanyBob<br />
| logo=Nintendo2016.svg<br />
| founded=1889-09-23<br />
| defunct=<br />
| mergedwith=<br />
| mergedinto=<br />
| headquarters=Kyoto, Japan<br />
}}<br />
<br />
'''Nintendo''' (kanji: 任天堂; kana: ニンテンドウ) is a company that makes video game consoles as well as develops and publishes video games. They were responsible for changing the video game industry into what it is today. Their flagship mascot is [[sonic:Mario|Mario]], an Italian plumber/carpenter. Nintendo was also [[Sega]]'s primary rival in the home console market before Sega stopped making consoles.<br />
<br />
==History==<br />
Nintendo was originally founded on September 23, 1889 by Fusajiro Yamauchi to produce handmade hanafuda cards, for use in a Japanese playing card game of the same name. The company entered other industries over the subsequent years, including the toy industry, but after a decade of business in the arcade industry and the worldwide success of the Game & Watch, they have primarily been in the consumer video game industry since the 1980s.<br />
<br />
Nintendo and Sega have been associated with each other as early as 1976, when Sega of America brought two of Nintendo's arcade games, ''[[Wild Gunman]]'' and ''[[Shooting Trainer]]'', over to the United States.{{magref|cb|1976-04-24|46|printpage=46}} Following [[Tokuzo Komai]]'s defection from Nintendo to Sega over the former's company's decision to move away from coin-op,{{magref|gamemachinejp|197|1}} the earliest indication of a rivalry between the two in the home console market began when Sega launched their [[SG-1000]] console on the same day Nintendo launched their Family Computer (Famicom) console in Japan - July 15, 1983. <br />
<br />
When Nintendo redesigned the Famicom into the [[Nintendo Entertainment System]] (NES) for the North American market in 1985, Sega then followed suit by launching the [[Sega Master System|Master System]] (a redesigned version of the [[Sega Mark III]]) the following year. Nintendo's subsequent systems (the Super Famicom/SNES and [[Nintendo 64]]) also competed with Sega's own home consoles for market share.<br />
<br />
Nintendo and Sega were present at the 1993 Congressional hearings on video game violence.<br />
<br />
After Sega left the hardware business following the discontinuation of the [[Dreamcast]], Sega started supporting Nintendo platforms as a third-party publisher, starting with the Game Boy Color, the [[Nintendo GameCube]] and the [[Game Boy Advance]].<br />
<br />
==Video game platforms==<br />
The four platforms below were not directly supported by Sega, but Sega's games were ported to them.<br />
* Family Computer/[[Nintendo Entertainment System]]<br />
* [[Game Boy]]<br />
* Super Famicom/[[Super Nintendo Entertainment System]]<br />
* [[Nintendo 64]]<br />
The platforms below are/were directly supported by Sega.<br />
* Game Boy Color<br />
* [[Game Boy Advance]]<br />
* [[Nintendo GameCube]]<br />
* [[Nintendo DS]]<br />
* [[Wii]]<br />
* [[Nintendo 3DS]]<br />
* [[Wii U]]<br />
* [[amiibo]]<br />
* [[Nintendo Switch]]<br />
<br />
==Softography==<br />
{{CompanyHistoryAll|Nintendo}}<br />
<br />
==Third-party games for Nintendo systems==<br />
The following Sega-licensed games were released for Nintendo's systems before Sega left the console market. Sixteen of them were approved by Nintendo, but four were not.<br />
<br />
===First set (1987-1990)===<br />
The third-party Nintendo licensees in this period were [[Sunsoft]], [[Takara]], [[Asmik]], [[Pony Canyon]], and [[Tecmo]]. [[Tengen]] released four Sega-licensed games for the NES without any approval from Nintendo, and it would be a factor in the legal battles between the two.<br />
;Family Computer games (Japan-only)<br />
#''[[Fantasy Zone]]'' (1987; [[Sunsoft]])<br />
#''[[Alien Syndrome]]'' (1988; Sunsoft)<br />
#''[[Fantasy Zone II: The Tears of Opa-Opa]]'' (1988; Sunsoft)<br />
#''[[Space Harrier]]'' (1989; [[Takara]])<br />
#''[[After Burner II]]'' (1989; Sunsoft)<br />
#''[[Juuouki]]'' (1990; [[Asmik]])<br />
;NES games (U.S.-only; Not approved by Nintendo)<br />
#''[[After Burner II]]'' (1989; [[Tengen]])<br />
#''[[Alien Syndrome]]'' (1989; Tengen)<br />
#''[[Shinobi]]'' (1989; Tengen)<br />
#''[[Fantasy Zone]]'' (1990; Tengen)<br />
;Game Boy games (Japan-only)<br />
#''[[Penguin Land (Game Boy)|Penguin Land]]'' (1990; [[Pony Canyon]])<br />
#''[[Head-On (Game Boy)|Head-On]]'' (1990; [[Tecmo]])<br />
<br />
===Second set (1998-2000)===<br />
The third-party Nintendo licensees in this period were [[Compile]] and [[Media Factory]].<br />
;Game Boy Color games (Japan-only)<br />
#''[[Pocket Puyo Puyo Sun]]'' (1998; [[Compile]])<br />
#''[[Puyo Puyo Gaiden: Puyo Wars]]'' (1999; Compile)<br />
#''[[Columns GB: Tezuka Osamu Characters]]'' (1999; [[Media Factory]])<br />
#''[[Arle no Bouken: Mahou no Jewel]]'' (2000; Compile)<br />
#''[[Sakura Taisen GB: Geki Hanagumi Nyuutai!]]'' (2000; Media Factory)<br />
#''[[Pocket Puyo Puyo~n]]'' (2000; Compile)<br />
;Super Famicom games (Japan-only)<br />
#''[[Columns]]'' (1999; Media Factory)<br />
;Nintendo 64 games (Japan-only)<br />
#''[[Puyo Puyo~n Party]]'' (1999; Compile)<br />
<br />
==Logos==<br />
<gallery><br />
Nintendo grey.svg<br />
Nintendo2016.svg<br />
</gallery><br />
<br />
==External links==<br />
{{NECRetro}}<br />
*[https://www.nintendo.co.jp/ Nintendo Japan]<br />
*[https://www.nintendo.com/us/ Nintendo of America]<br />
*[https://www.nintendo.com/en-ca/ Nintendo of Canada]<br />
*[https://www.nintendo.com/es-mx/ Nintendo Mexico]<br />
*[https://www.nintendo.com/pt-br/ Nintendo Brazil]<br />
*[https://www.nintendo.co.uk Nintendo UK]<br />
*[https://www.nintendo-europe.com/ Nintendo of Europe]<br />
*[https://www.nintendo.de/ Nintendo Germany]<br />
*[https://www.nintendo.at/ Nintendo Austria]<br />
*[https://www.nintendo.ch/de/ Nintendo Switzerland]<br />
*[https://www.nintendo.fr/ Nintendo France]<br />
*[https://www.nintendo.it/ Nintendo Italy] <br />
*[https://www.nintendo.nl/ Nintendo Netherlands]<br />
*[https://www.nintendo.be/nl/ Nintendo Belgium]<br />
*[https://www.nintendo.es/ Nintendo Spain]<br />
*[https://www.nintendo.pt/ Nintendo Portugal]<br />
*[https://www.nintendo.com.au/ Nintendo Australia]<br />
*[https://www.nintendo.com.hk/ Nintendo Hong Kong]<br />
*[https://www.nintendo.com.tw/ Nintendo Taiwan]<br />
*[https://www.nintendo.co.kr/ Nintendo of Korea]<br />
<br />
==References==<br />
<references/><br />
<br />
[[Category:Licensors]]</div>Clownacyhttps://segaretro.org/index.php?title=Nemesis_compression&diff=962908Nemesis compression2024-02-26T16:10:16Z<p>Clownacy: /* Compression Theory */ Added a section explaining the method Sega's compressor used to perform Nemesis compression.</p>
<hr />
<div>'''Nemesis compression''' is the method created by [[Sega]] to reduce the amount of space that graphics data takes up in a [[Sega Mega Drive]] [[ROM]]. A decompression algorithm takes the compressed data, unpacks it and transfers it to the [[VRAM]]. The graphics can then be displayed on the screen. The Nemesis format is specifically designed for Mega Drive graphics, as it relies on the length of the data being divisible by $20 (hex), which is the exact number of bytes in a single [[8x8 tile]]. However, Nemesis compression is also used for 16x16 [[block mappings]] in Sonic CD, because the data conforms to the $20 rule.<br />
<br />
Nemesis compression is named after Nemesis, the hacker who first created a program to decompress it. The format is used in numerous Mega Drive games, especially [[Sonic the Hedgehog]] games.<br />
<br />
==Compression Theory==<br />
The Nemesis compression format uses both [[wikipedia:Run-length_encoding|run-length encoding]] and [[wikipedia:Entropy_encoding|entropy encoding]] to compress data. The source data is broken into nybbles which are then grouped into runs of 1 to 8 nybbles in length; there are multiple ways to do this grouping, which is called a ''parse''. Given a parse of the file into nybble runs, the file will then be entropy encoded based on the frequency of each nybble run in the file; the code of each nybble run is used to build a dictionary which is used when encoding and decoding the file.<br />
<br />
The final Nemesis compressed file is then composed of a 2-byte header, a dictionary associating nybble runs to their respective codes, and a bitstream (the ''encoded bitstream'') where each nybble run in the parse is replaced with its corresponding code in the dictionary. The dictionary is present in the compressed file so that it is possible to decode it; the decoder used in Mega Drive [[ROM]]s converts the dictionary into a simple table, using the code read as an index.<br />
<br />
There are some restrictions to what forms of entropy encoding can be used: first, is limited to 8 bits for each encoded nybble run; this happens because the dictionary leaves only 8 bits for each code. Second, the set of all codes in the dictionary must form a [[wikipedia:prefix-free code|prefix-free code]]; this makes the encoded bitstream unambiguous in its decoding, but it reduces the number of codes that can be used when entropy-encoding the file. Third, a nibble run can be directly inlined using a special 6-bit code prefix that was specified in the format; because the entropy encoding must result in a prefix-free code, neither this inlining bit pattern, nor any of its prefixes, can be used as codes when building the dictionary.<br />
<br />
As noted above, there are multiple ways to parse the input file into nybble runs; each such parse will give rise to different dictionaries because the different frequencies of the nybble runs will change the resulting entropy encoding. Given a parse, the [[wikipedia:Package-merge_algorithm|package-merge algorithm]] can be used to find an optimal dictionary; but since it is not possible to know the length of each dictionary entry beforehand, or how many entries are useful to have in the dictionary, the final file size can't be known during the parsing stage. Finding a parse that gives the smallest possible file size is difficult, particularly since the number of possible parses is staggering even for a small file. Nevertheless, more modern techniques, including the aforementioned package-merge algorithm, have generally improved compression ratios compared to what was found within Mega Drive [[ROM]]s.<br />
<br />
The high compression rate offered by the Nemesis compression format made it a very appropriate format for cartridge-based systems, where storage space was at a premium. Although the Nemesis format provided high compression, it also took a fair amount of time for the [[68000]] CPU to decompress. To prevent noticeable stalls while loading new sets of tiles into the VRAM, the Nemesis decompression routine limited the console to decompressing a maximum of 3 tiles worth of pattern data each frame; some variants of the decoding routines can decode 6 or even 12 tiles in a frame (with a correspondingly larger decompression buffer), but they are much more rarely used.<br />
<br />
===Sega's Compressor===<br />
The compressor that was used to compress tile data in ''[[Sonic 1]]'', ''[[Sonic 2]]'', ''[[Sonic 3]]'', ''[[Sonic & Knuckles]]'', and presumably other titles, used [[wikipedia:Shannon-Fano coding|Shannon-Fano coding]] rather than Huffman coding. In particular, it used Fano's Method to compute prefix-free codes. A [[wikipedia:selection sort|selection sort]] was used to assign the shortest codes to the most common nybble runs. While Sega's compressor has yet to be found and made publicly available, these behaviours can be recreated to produce a compressor that outputs identical data. [[clownnemesis]] is one such compressor.<br />
<br />
==Format Description==<br />
In order to understand Nemesis compression it is vital to know how the Mega Drive stores graphics. Graphics are stored in the form of 8x8 tiles known as patterns. Each pixel in a pattern is represented by a single nybble, that nybble being the [[Palette#Mega Drive Palette|palette]] index to use for that pixel. One pattern therefore takes up 8 * 8 = 64 nybbles or 32 bytes.<br />
<br />
Nemesis compression works by replacing the most common nybble runs with codes representing that run. A [[wikipedia:prefix-free code|prefix-free code]] system is used, meaning that no valid code can be a prefix of a longer valid code. For example, if 10 is a valid 2-bit code, 110 is a valid 3-bit code but 100 isn't (because it starts with 10). The length of each code is selected according to the frequency of the nybble run that code represents - the most commonly occurring runs will be represented using shorter codes.<br />
<br />
The Nemesis compressor can operate in two modes: normal mode, in which each row of pixels in a pattern is encoded as-is, and XOR mode, in which each row of pixels in a pattern is encoded in terms of its differences from the previous row. The first word in a Nemesis-compressed file gives the number of patterns in the uncompressed data (i.e. the size of the uncompressed data / $20). The sign bit of this word being set indicates that the file uses XOR mode instead of normal mode.<br />
<br />
Following this word is a section which describes the codes used in the file. The lower nybble of the first byte gives the palette index. The upper nybble of the next byte gives the number of times that palette index is to be copied - 1, its lower nybble is the length of the code in bits, and the byte after that gives the actual code itself. The byte following this can be interpreted in three ways. If it's FF, it marks the end of the section. Otherwise, if its sign bit is set, its lower nybble gives the new palette index and the two bytes following it have the same format as described above. If its sign bit is clear, however, the palette index remains unchanged and the byte contains the copy count and code length with the actual code being stored in the next byte, as described above. The process repeats until the end of the section is encountered, and a code table is built up in RAM to be used in the next stage of the decompression.<br />
<br />
The next section of the file contains the actual compressed data, which is stored as a series of bits. The bit series 111111 has a special purpose: it indicates inline data, and the 7 bits following this series have the format XXXYYYY, where YYYY gives the palette index and XXX gives the copy count - 1. All other series represent a code, and the palette index and copy count for that code are fetched from the code table. When an entire row of a pattern (i.e. 8 pixels/4 bytes long) has been decompressed, it is written directly to the destination if in normal mode, or XORed by the previous row and then written to the destination if in XOR mode. The decompression terminates when the number of decompressed patterns matches the pattern count given in the first word of the file.<br />
<br />
==Usage in Mega Drive Games==<br />
The Nemesis compression format was widely used in many Mega Drive games, both those produced by Sega, as well as a variety of third party developers. Additionally, the decompression routine for Nemesis archives embedded in ROMs that use the format is identical in the games in which it was used. It can be concluded from this that the Nemesis compression format was included as one of the standard libraries provided by Sega in their SDK for the console.<br />
<br />
Although Nemesis archives were used for all the compressed art in ''[[Sonic 1]]'', for ''[[Sonic 2]]'', the main block of art used for level tiles in each stage was compressed using the [[Kosinski compression]] format. This was almost certainly done to decrease load times at the start of the level. Kosinski is an LZ77-based compression algorithm, which provides extremely fast decompression. While the Nemesis format was limited to only 3 tiles of decompressed data per frame, the Kosinski decompression routine may be able to decompress 100 tiles in the same time. This could eliminate up to 3 seconds worth of load times from the start of a level. Although Kosinski compression offered a lightning fast decompression rate, the algorithm was not well suited to the large number of small matches that generally occur in most tiles. As a result, Kosinski compression generally produced a much lower compression ratio than the Nemesis format achieves for Mega Drive art tiles. Additionally, while the Nemesis format could compress any data in 2 passes, the number of passes required with the Kosinski format increased with the size of the data. Kosinski could potentially require hundreds or even thousands of passes over the data to achieve its maximum compression ratios. As a result, the Kosinski format provided much slower compression times, which although insignificant today, may have significantly increased the time it would have taken developers to build test ROMs during development.<br />
<br />
For ''[[Sonic 3]]'' and ''[[Sonic & Knuckles]]'', most of the art was compressed using Kosinski compression. Despite the lower compression ratio, the use of Kosinski allowed the developers to make large changes to the appearance of the level between acts, and even during the level, without any apparent seams, and without causing visible slowdowns. This was a key factor in creating some of the indoor/outdoor and other mid-level transitions used throughout these games, and allowed the developers to create maps which had much more variety within each level. The extensive use of Kosinski compression for art contributed to the larger ROM size for these later games: 2MB for each game, as opposed to 512KB for Sonic 1, and 1MB for Sonic 2.<br />
<br />
==Sega Mega Drive games which use Nemesis compression==<br />
:''This list is vastly incomplete; please help expand it.<br />
{{multicol|<br />
* ''[[Alien Storm (Mega Drive)|Alien Storm]]''<br />
* ''[[Bare Knuckle 2]]'' (beta only)<br />
* ''[[Castle of Illusion]]''<br />
* ''[[Chaotix]]'' ([[32X]])<br />
* ''[[Columns]]''<br />
* ''[[Dr. Robotnik's Mean Bean Machine]]'' (only for some art — the rest is done using a custom compression introduced in ''[[Puyo Puyo]]'')<br />
* ''[[ESWAT: City Under Siege]]''<br />
* ''[[Fatal Labyrinth]]''<br />
* ''[[Flicky]]''<br />
* ''[[Forgotten Worlds (Mega Drive)|Forgotten Worlds]]''<br />
* ''[[Ghostbusters]]''<br />
* ''[[Ghouls 'n' Ghosts]]''<br />
* ''[[Golden Axe]]''<br />
* ''[[Golden Axe 2]]''<br />
* ''[[Golden Axe 3]]''<br />
* ''[[Jewel Master]]'' (also contains uncompressed graphics)<br />
* ''[[Magical Taruruto-kun (Mega Drive)|Magical Taruruto-kun]]''<br />
* ''[[Mercs]]''<br />
* ''[[Moonwalker]]''<br />
* ''[[MUSHA]]''<br />
* ''[[Phantasy Star II]]'' (partially — some art use another simpler compression scheme, some is uncompressed)<br />
* [[Phantasy Star II Text Adventures|''Phantasy Star II'' Text Adventures]]<br />
* ''[[Phantasy Star III]]''<br />
* ''[[Phantasy Star IV]]''<br />
* ''[[Psy-O-Blade]]''<br />
* ''[[Pulseman]]''<br />
* ''[[Quackshot]]'' (graphics)<br />
* ''[[Revenge of Shinobi]]''<br />
* ''[[Ristar]]''<br />
* [[Sega Mega Anser]]<br />
* [[Sega Mega-CD]] BIOS<br />
* ''[[Shadow Dancer: The Secret of Shinobi]]''<br />
* ''[[Sonic & Knuckles]]''<br />
* ''[[Sonic Compilation]]'' (menu & games)<br />
* ''[[Sonic Crackers]]''<br />
* ''[[sonic:Sonic Eraser|Sonic Eraser]]''<br />
* ''[[Sonic Jam]]'' ([[Saturn]])<br />
* ''[[Sonic the Hedgehog (16-bit)|Sonic the Hedgehog]]''<br />
* ''[[Sonic the Hedgehog 2 (16-bit)|Sonic the Hedgehog 2]]''<br />
* ''[[Sonic the Hedgehog 3]]''<br />
* ''[[Sonic the Hedgehog CD]]'' ([[Mega-CD]])<br />
* ''[[Streets of Rage]]''<br />
* ''[[Streets of Rage 3]]''<br />
* ''[[Strider]]''<br />
* ''[[Super Hang-On]]''<br />
* ''[[Super Monaco GP]]''<br />
* ''[[Twin Cobra]]'' (also contains uncompressed graphics)<br />
* ''[[World Cup Italia '90]]''<br />
* ''[[World of Illusion]]''<br />
}}<br />
<br />
== Decompression code ==<br />
<br />
An annotated version of the Nemesis decompression code is provided below for reference. The code is taken from ''[[sonic:Sonic 3 & Knuckles|Sonic 3 & Knuckles]]'', but the same or similar code is used in all the games which use the format.<br />
<br />
<pre>; ---------------------------------------------------------------------------<br />
; Nemesis decompression subroutine, decompresses art directly to VRAM<br />
; Inputs:<br />
; a0 = art address<br />
; a VDP command to write to the destination VRAM address must be issued<br />
; before calling this routine<br />
; ---------------------------------------------------------------------------<br />
<br />
; =============== S U B R O U T I N E =======================================<br />
<br />
<br />
Nem_Decomp:<br />
movem.l d0-a1/a3-a5,-(sp)<br />
lea (Nem_PCD_WriteRowToVDP).l,a3<br />
lea (VDP_data_port).l,a4 ; write all rows to the VDP data port<br />
bra.s Nem_Decomp_Main<br />
; End of function Nem_Decomp<br />
<br />
; ---------------------------------------------------------------------------<br />
; Nemesis decompression subroutine, decompresses art to RAM<br />
; Inputs:<br />
; a0 = art address<br />
; a4 = destination RAM address<br />
; ---------------------------------------------------------------------------<br />
<br />
; =============== S U B R O U T I N E =======================================<br />
<br />
<br />
Nem_Decomp_To_RAM:<br />
movem.l d0-a1/a3-a5,-(sp)<br />
lea (Nem_PCD_WriteRowToRAM).l,a3<br />
; End of function Nem_Decomp_To_RAM<br />
<br />
; ---------------------------------------------------------------------------<br />
; Main Nemesis decompression subroutine<br />
; ---------------------------------------------------------------------------<br />
<br />
; =============== S U B R O U T I N E =======================================<br />
<br />
<br />
Nem_Decomp_Main:<br />
lea (Nem_code_table).w,a1<br />
move.w (a0)+,d2 ; get number of patterns<br />
lsl.w #1,d2<br />
bcc.s + ; branch if the sign bit isn't set<br />
adda.w #Nem_PCD_WriteRowToVDP_XOR-Nem_PCD_WriteRowToVDP,a3 ; otherwise the file uses XOR mode<br />
+<br />
lsl.w #2,d2 ; get number of 8-pixel rows in the uncompressed data<br />
movea.w d2,a5 ; and store it in a5 because there aren't any spare data registers<br />
moveq #8,d3 ; 8 pixels in a pattern row<br />
moveq #0,d2<br />
moveq #0,d4<br />
bsr.w Nem_Build_Code_Table<br />
move.b (a0)+,d5 ; get first byte of compressed data<br />
asl.w #8,d5 ; shift up by a byte<br />
move.b (a0)+,d5 ; get second byte of compressed data<br />
move.w #$10,d6 ; set initial shift value<br />
bsr.s Nem_Process_Compressed_Data<br />
movem.l (sp)+,d0-a1/a3-a5<br />
rts<br />
; End of function Nem_Decomp_Main<br />
<br />
; ---------------------------------------------------------------------------<br />
; Part of the Nemesis decompressor, processes the actual compressed data<br />
; ---------------------------------------------------------------------------<br />
<br />
; =============== S U B R O U T I N E =======================================<br />
<br />
; PCD is used throughout this subroutine as an initialism for Process_Compressed_Data<br />
Nem_Process_Compressed_Data:<br />
move.w d6,d7<br />
subq.w #8,d7 ; get shift value<br />
move.w d5,d1<br />
lsr.w d7,d1 ; shift so that high bit of the code is in bit position 7<br />
cmpi.b #%11111100,d1 ; are the high 6 bits set?<br />
bcc.s Nem_PCD_InlineData ; if they are, it signifies inline data<br />
andi.w #$FF,d1<br />
add.w d1,d1<br />
move.b (a1,d1.w),d0 ; get the length of the code in bits<br />
ext.w d0<br />
sub.w d0,d6 ; subtract from shift value so that the next code is read next time around<br />
cmpi.w #9,d6 ; does a new byte need to be read?<br />
bcc.s + ; if not, branch<br />
addq.w #8,d6<br />
asl.w #8,d5<br />
move.b (a0)+,d5 ; read next byte<br />
+<br />
move.b 1(a1,d1.w),d1<br />
move.w d1,d0<br />
andi.w #$F,d1 ; get palette index for pixel<br />
andi.w #$F0,d0<br />
<br />
Nem_PCD_GetRepeatCount:<br />
lsr.w #4,d0 ; get repeat count<br />
<br />
Nem_PCD_WritePixel:<br />
lsl.l #4,d4 ; shift up by a nybble<br />
or.b d1,d4 ; write pixel<br />
subq.w #1,d3 ; has an entire 8-pixel row been written?<br />
bne.s Nem_PCD_WritePixel_Loop ; if not, loop<br />
jmp (a3) ; otherwise, write the row to its destination<br />
; ---------------------------------------------------------------------------<br />
<br />
Nem_PCD_NewRow:<br />
moveq #0,d4 ; reset row<br />
moveq #8,d3 ; reset nybble counter<br />
<br />
Nem_PCD_WritePixel_Loop:<br />
dbf d0,Nem_PCD_WritePixel<br />
bra.s Nem_Process_Compressed_Data<br />
; ---------------------------------------------------------------------------<br />
<br />
Nem_PCD_InlineData:<br />
subq.w #6,d6 ; 6 bits needed to signal inline data<br />
cmpi.w #9,d6<br />
bcc.s +<br />
addq.w #8,d6<br />
asl.w #8,d5<br />
move.b (a0)+,d5<br />
+<br />
subq.w #7,d6 ; and 7 bits needed for the inline data itself<br />
move.w d5,d1<br />
lsr.w d6,d1 ; shift so that low bit of the code is in bit position 0<br />
move.w d1,d0<br />
andi.w #$F,d1 ; get palette index for pixel<br />
andi.w #$70,d0 ; high nybble is repeat count for pixel<br />
cmpi.w #9,d6<br />
bcc.s Nem_PCD_GetRepeatCount<br />
addq.w #8,d6<br />
asl.w #8,d5<br />
move.b (a0)+,d5<br />
bra.s Nem_PCD_GetRepeatCount<br />
; ---------------------------------------------------------------------------<br />
<br />
Nem_PCD_WriteRowToVDP:<br />
move.l d4,(a4) ; write 8-pixel row<br />
subq.w #1,a5<br />
move.w a5,d4 ; have all the 8-pixel rows been written?<br />
bne.s Nem_PCD_NewRow ; if not, branch<br />
rts ; otherwise the decompression is finished<br />
; ---------------------------------------------------------------------------<br />
<br />
Nem_PCD_WriteRowToVDP_XOR:<br />
eor.l d4,d2 ; XOR the previous row by the current row<br />
move.l d2,(a4) ; and write the result<br />
subq.w #1,a5<br />
move.w a5,d4<br />
bne.s Nem_PCD_NewRow<br />
rts<br />
; ---------------------------------------------------------------------------<br />
<br />
Nem_PCD_WriteRowToRAM:<br />
move.l d4,(a4)+<br />
subq.w #1,a5<br />
move.w a5,d4<br />
bne.s Nem_PCD_NewRow<br />
rts<br />
; ---------------------------------------------------------------------------<br />
<br />
Nem_PCD_WriteRowToRAM_XOR:<br />
eor.l d4,d2<br />
move.l d2,(a4)+<br />
subq.w #1,a5<br />
move.w a5,d4<br />
bne.s Nem_PCD_NewRow<br />
rts<br />
; End of function Nem_Process_Compressed_Data<br />
<br />
; ---------------------------------------------------------------------------<br />
; Part of the Nemesis decompressor, builds the code table (in RAM)<br />
; ---------------------------------------------------------------------------<br />
<br />
; =============== S U B R O U T I N E =======================================<br />
<br />
; BCT is used throughout this subroutine as an initialism for Build_Code_Table<br />
Nem_Build_Code_Table:<br />
move.b (a0)+,d0 ; read first byte<br />
<br />
Nem_BCT_ChkEnd:<br />
cmpi.b #$FF,d0 ; has the end of the code table description been reached?<br />
bne.s Nem_BCT_NewPalIndex ; if not, branch<br />
rts ; otherwise, this subroutine's work is done<br />
; ---------------------------------------------------------------------------<br />
<br />
Nem_BCT_NewPalIndex:<br />
move.w d0,d7<br />
<br />
Nem_BCT_Loop:<br />
move.b (a0)+,d0 ; read next byte<br />
cmpi.b #$80,d0 ; sign bit being set signifies a new palette index<br />
bcc.s Nem_BCT_ChkEnd ; a bmi could have been used instead of a compare and bcc<br />
move.b d0,d1<br />
andi.w #$F,d7 ; get palette index<br />
andi.w #$70,d1 ; get repeat count for palette index<br />
or.w d1,d7 ; combine the two<br />
andi.w #$F,d0 ; get the length of the code in bits<br />
move.b d0,d1<br />
lsl.w #8,d1<br />
or.w d1,d7 ; combine with palette index and repeat count to form code table entry<br />
moveq #8,d1<br />
sub.w d0,d1 ; is the code 8 bits long?<br />
bne.s Nem_BCT_ShortCode ; if not, a bit of extra processing is needed<br />
move.b (a0)+,d0 ; get code<br />
add.w d0,d0 ; each code gets a word-sized entry in the table<br />
move.w d7,(a1,d0.w) ; store the entry for the code<br />
bra.s Nem_BCT_Loop ; repeat<br />
; ---------------------------------------------------------------------------<br />
<br />
; the Nemesis decompressor uses prefix-free codes (no valid code is a prefix of a longer code)<br />
; e.g. if 10 is a valid 2-bit code, 110 is a valid 3-bit code but 100 isn't<br />
; also, when the actual compressed data is processed the high bit of each code is in bit position 7<br />
; so the code needs to be bit-shifted appropriately over here before being used as a code table index<br />
; additionally, the code needs multiple entries in the table because no masking is done during compressed data processing<br />
; so if 11000 is a valid code then all indices of the form 11000XXX need to have the same entry<br />
Nem_BCT_ShortCode:<br />
move.b (a0)+,d0 ; get code<br />
lsl.w d1,d0 ; shift so that high bit is in bit position 7<br />
add.w d0,d0 ; get index into code table<br />
moveq #1,d5<br />
lsl.w d1,d5<br />
subq.w #1,d5 ; d5 = 2^d1 - 1<br />
<br />
Nem_BCT_ShortCode_Loop:<br />
move.w d7,(a1,d0.w) ; store entry<br />
addq.w #2,d0 ; increment index<br />
dbf d5,Nem_BCT_ShortCode_Loop ; repeat for required number of entries<br />
bra.s Nem_BCT_Loop<br />
; End of function Nem_Build_Code_Table</pre><br />
<br />
[[Category:Data compression]]</div>Clownacyhttps://segaretro.org/index.php?title=YM2612&diff=962892YM26122024-02-26T13:50:50Z<p>Clownacy: Added a link to the official manual.</p>
<hr />
<div>{{cleanup}}<br />
{{ICBob<br />
| image=Ym2612.jpg<br />
| title=<br />
| designer=[[Yamaha]]<br />
| date=<br />
}}<br />
The '''Yamaha YM2612''' (also incorrectly called YM-2612) is a sound synthesizer integrated circuit by [[Yamaha]] [https://upload.wikimedia.org/wikipedia/commons/0/05/Yamaha_YM2612_top_metal_die_shot.jpg known to have first appeared in 1988]. The chip implements Yamaha Operator Type-N (OPN) frequency modulation synthesis, and is given the designation '''OPN2''', however it is not the second OPN chip — the YM2203 (OPN), YM2608 (OPNA) and YM2610 (OPNB) are known to precede it. A CMOS version, the '''YM3438'''/'''OPN2C''', was also manufactured by Yamaha.<br />
<br />
By default, the chip can generate six simultaneous tones, each with their own configuration of FM operators. As with all OPN chips, the third channel can be modified to have each operator run at a different frequency — this is often called "special" or "multifrequency" mode. The sixth channel can be swapped out for a software-controlled 8-bit PCM channel mixed directly into the output waveform. Finally, there is a single LFO which acts on all FM channels, but each channel can be set to be affected by it differently.<br />
<br />
The YM2612/YM3438 was only notably used on the [[Sega Mega Drive]] game console, [[Sega System 32]] arcade board, and the Fujitsu FM Towns computer. However, its use on the Mega Drive meant it was also used on hardware derived from it — including arcade boards, where the YM3438 was used. Several Mega Drive 2s also used the YM3438 core.<br />
<br />
==Details==<br />
{{stub}}<br />
OPN FM synthesis is similar to other forms of Yamaha FM synthesis, in that it consists of a number of operators connected in a variety of ways, each operator consisting of a modified ADSR envelope, rate scaling, frequency multiplication, detuning, and a SSG envelope generator (the YM2612 does not include the YM2149 [AY-3-8910 clone] core found in other OPN chips, but the envelope generator remains).<br />
<br />
The YM2612 does not have a separate address and data bus. As a result, communication with the YM2612 is multiplexed on the 8-bit parallel bus. Each parameter the chip provides is accessed by first sending a register number to the chip, then the register's value. Because Yamaha's register layout only allows four channels on a single register map, the YM2612 uses two ports to access each group of three channels.<br />
<br />
The YM2612 also contains two timers — the high frequency Timer A and lower frequency Timer B. While the YM2612 can be set to interrupt a CPU when a timer reaches zero, sadly Sega did not make this connection on the Mega Drive, requiring timers to be checked in software.<br />
<br />
When Channel 6 is in DAC mode, the controlling CPU must stream 8-bit unsigned PCM data to the YM2612 fast enough to be played back at the optimal playback speed. The maximum sample rate depends on the sample rate of the chip, but keep in mind that register writes must be synchronized to when the chip is ready — this is checked by polling the YM2612's status register and seeing if its Busy bit is set or not.<br />
<br />
==Technical specifications==<br />
:''See [[Sega Mega Drive/Technical specifications|Sega Mega Drive: Technical specifications]] for further information''<br />
<br />
* Clock rate:<br />
:* [[Sega Mega Drive]]: 7.670453 MHz (NTSC), 7.600489 MHz (PAL)<br />
:* [[Sega System 32]]: 8.053975 MHz<br />
* Sound output: Mono, Stereo{{fileref|GenesisTechnicalOverview.pdf}}<br />
:* Output frequency: 53.267 kHz (NTSC), 52.781 kHz (PAL){{ref|[https://github.com/RetroAchievements/RASuite/blob/master/bizhawk/BizHawk.Emulation.Common/Sound/YM2612.cs Yamaha YM2612 Emulation Core]}}<br />
* Sound channels: 6<br />
:* Default configuration: 6 channels (6 FM channels)<br />
:* Alternative configuration: 6 channels (5 FM channels, 1 PCM channel)<br />
* [[wikia:w:c:electronicmusic:Frequency modulation|FM synthesis]]:<br />
:* FM channels: 5-6 channels (5 channels with PCM, 6 channels without PCM)<br />
:* FM sample rate: 53.267 kHz (NTSC), 52.781 kHz (PAL){{ref|[https://github.com/RetroAchievements/RASuite/blob/master/bizhawk/BizHawk.Emulation.Common/Sound/YM2612.cs Yamaha YM2612 Emulation Core]}}<br />
* [[PCM]] [[wikipedia:Sampling (signal processing)|sampling]] in Channel 6 [[wikipedia:Digital-to-analog converter|DAC]] mode:<br />
::* Sample [[wikipedia:Audio bit depth|depth]]: 8‑bit{{ref|[http://www.alyjameslab.com/wa_files/FMDRIVE_USER_MANUAL.pdf FM-Drive User Manual]}}<br />
::* [[wikipedia:Sampling rate|Sample rate]]:<br />
:::* Maximum: over 44.1 kHz{{ref|1=[https://www.youtube.com/watch?v=fYWclV9H2eY YM2612 with Teensy: playing audio at 44.1 kHz]}}<br />
:::* Sega Mega Drive: 26.3 kHz<br />
:::* Sega System 32: ~29 kHz<br />
* [[wikipedia:Low-frequency oscillation|LFO]]: 1 [[wikipedia:sine wave|sine wave]] LFO (low frequency oscillator) channel<br />
* [[wikipedia:Interrupt request|IRQ]] interrupt capabilities: IRQ2 sound interrupt{{ref|[https://github.com/mamedev/mess-cvs/blob/master/src/drivers/genesis.c Genesis (MESS)]}}<br />
<br />
==Documentation==<br />
<gallery><br />
YM2612 manual.pdf|Official manual<br />
</gallery><br />
<br />
==External links==<br />
*[http://www7.plala.or.jp/kikekike/fm/ YM3438 information, including official manuals (Japanese, link is now dead.)] ([http://web.archive.org/web/20140804044038/http://www7.plala.or.jp/kikekike/fm/ Archived, not complete])<br />
*[http://www.smspower.org/maxim/Documents/YM2612 A transcription of Sega's '''incomplete, sometimes incorrect''' YM2612 documentation from the sega2.doc file]<br />
<br />
==References==<br />
<references /></div>Clownacyhttps://segaretro.org/index.php?title=File:YM2612_manual.pdf&diff=962891File:YM2612 manual.pdf2024-02-26T13:49:19Z<p>Clownacy: An official YM2612 manual. Sourced from Hidden Palace's SMPS source code release, where it is labelled 'the green folder'.
https://hiddenpalace.org/News/Sega_of_Japan_Sound_Documents_and_Source_Code
Category:Hardware documentation files</p>
<hr />
<div>== Summary ==<br />
An official YM2612 manual. Sourced from Hidden Palace's SMPS source code release, where it is labelled 'the green folder'.<br />
https://hiddenpalace.org/News/Sega_of_Japan_Sound_Documents_and_Source_Code<br />
<br />
[[Category:Hardware documentation files]]</div>Clownacyhttps://segaretro.org/index.php?title=SMPS&diff=962889SMPS2024-02-26T13:27:15Z<p>Clownacy: Add Sega Pico to the list of consoles in the intro.</p>
<hr />
<div>'''Sample Music Playback System''' ('''SMPS''') is the common name of a family of audio playback engines (or "drivers") and storage formats used by various [[Sega]] consoles (including the [[Sega Mega Drive]], [[Sega Mega-CD]], [[Sega 32X]], [[Sega Master System]], [[Sega Game Gear]], and [[Sega Pico]]). "SMPS" is thought to be a colloquial term - there is no evidence to suggest this was the naming scheme of any official drivers, but is the most widely accepted name for the system.<br />
<br />
Like other sound drivers, SMPS was designed as a means of processing audio information, allowing a console's CPU to communicate with sound chips on the board and create audible sound (i.e. "driving" the sound). It is usually associated with first-party Japanese Mega Drive games (where it was most predominantly used) - analogous to [[Sega of America]]'s use of the [[GEMS]] driver, and began appearing in games from the late 1980s until the aforementioned consoles bowed out of the market.<br />
<br />
By sharing drivers between games, developers could create tools to quickly produce audio, and it allows for music and sound effects to be more easily ported between games.<br />
<br />
==Variants==<br />
===Mega Drive and 32X===<br />
Mega Drive (and by extension, 32X) developers had a choice of which processor to run SMPS on; the 16-bit [[68000]], or the 8-bit [[Z80]]. The driver variants are known as '''SMPS 68000''' and '''SMPS Z80''' respectively.<br />
<br />
Some developers, such as [[Treasure]], chose to modify the driver, effectively making their own variants. Individual games such as ''[[Ristar]]'' also have their own modified drivers.<br />
<br />
====Source code====<br />
The source code to both SMPS-68000 and SMPS-Z80 was found and released by Hidden Palace in 2020[https://hiddenpalace.org/News/Sega_of_Japan_Sound_Documents_and_Source_Code]. The versions of the two drivers appear to be SMPS-68000 Type 1B and SMPS-Z80 Type 2 DAC.<br />
<br />
{{Download<br />
| title=SMPS-68000 source code<br />
| file=SMPS-68000_source_code.zip<br />
}}<br />
{{Download<br />
| title=SMPS-Z80 source code<br />
| file=SMPS-Z80_source_code.zip<br />
}}<br />
<br />
====Games which use SMPS 68000====<br />
=====Mega Drive=====<br />
{{SoundDriverList|SMPS 68000|MD}}<br />
<br />
=====32X=====<br />
{{SoundDriverList|SMPS 68000|32X}}<br />
<br />
====Games which use SMPS Z80====<br />
=====Mega Drive=====<br />
{{SoundDriverList|SMPS Z80|MD}}<br />
<br />
=====32X=====<br />
{{SoundDriverList|SMPS Z80|32X}}<br />
<br />
===Mega-CD===<br />
'''SMPS-PCM''' is variant of SMPS-68000 designed to work on the Mega-CD's second 68000 processor, giving it access to the system's [[RF5C164]] PCM chip.<br />
<br />
===Master System and Game Gear===<br />
SMPS drivers designed to work on the Z80 processors of the Master System and Game Gear were also produced. These tap into the two consoles' [[SN76489]] chip.<br />
<br />
===Pico===<br />
'''SMPS-Pico''' is a variant of SMPS-68000 that targets the Sega Pico. It plays audio using the [[SN76489]] and the Pico-specific [[UPD7759]] chip.<br />
<br />
The source code to this particular SMPS variant was released on AssemblerGames some time around 2016.<br />
<br />
{{Download<br />
| title=Sega Pico Dev Tools<br />
| file=SEGA_Pico_dev_tools.zip<br />
}}<br />
<br />
==Naming==<br />
The 'true' name of SMPS remains a subject of debate. Analysis of the source code reveals various possible names:<br />
<br />
{| prettytable" style="width:auto;<br />
! Name !! Usage<br />
|-<br />
| Sound<br />
| Appears frequently in documentation (m5_edit.jxw, ver11.doc, etc.). In the source code, this is the name of the label that marks the driver's entry point (m5cnt13.src, mdcnt11.asm).<br />
|-<br />
| Sound-Sorce<br />
| Appears in the header at the top of SMPS-Z80's source code files. Included with the source code is a [[wikipedia:sed|sed]] script that replaces the instances of this name with a parameter that is labelled 'game name'. This script was seemingly used on a handful of files, replacing 'Sound-Sorce' with 'MODEM_BOOT_ROM' and 'DICK_TRACY'.<br />
|-<br />
| Sound-Source<br />
| Appears in the header at the top of SMPS-68000's and SMPS-Pico's source code files. It is also the name used by some developers who had used SMPS back in the 90s[https://web.archive.org/web/20191006015702/https://twitter.com/Hikoshi_H/status/1180661206253596672][https://web.archive.org/web/20190920174036/https://twitter.com/Hikoshi_H/status/1169707879164608513][https://web.archive.org/web/20200719143541/https://twitter.com/Mazin__/status/105869176442331136]. Included with the source code is a sed script that replaces the instances of this name with a parameter that is labelled 'game name'.<br />
|-<br />
| Sound-Sample<br />
| Written on the SMPS-68000 and SMPS-Z80 source code's floppy disks. The SMPS-68000 source code has a Batch script (fmk.bat) that uses the aforementioned sed script to replace 'Sound-Source' with 'Sound-Sample'.<br />
|-<br />
| EASYSND<br />
| The name of the zip file that holds another zip file which contains the SMPS-Pico source code.<br />
|-<br />
| PICOSND<br />
| The name of the zip file which contains the SMPS-Pico source code. Also appears in various filenames and build scripts.<br />
|-<br />
| The PICO sound driver<br />
| Used by SMPS-Pico's GENERIC.MAK and PICOSND.MAK files.<br />
|}<br />
<br />
==Technical details==<br />
*[[SMPS/Headers|Headers]]<br />
*[[SMPS/Voices and samples|Voices and samples]]<br />
*[[SMPS/Song data|Song data]]<br />
<br />
==Tools==<br />
*[[xm4smps]]<br />
*[[xm3smps/oerg]] (official improved branch of [[xm3smps]])<br />
<br />
== External links ==<br />
*[http://gdri.smspower.org/wiki/index.php/Mega_Drive/Genesis_Sound_Engine_List A list of the sound engines used on the Mega Drive]<br />
<br />
==References==<br />
<references /><br />
[[Category:Mega Drive sound drivers]]<br />
[[Category:SMPS]]</div>Clownacyhttps://segaretro.org/index.php?title=Sound-Sorce&diff=962888Sound-Sorce2024-02-26T13:26:08Z<p>Clownacy: Redirect to SMPS.</p>
<hr />
<div>#REDIRECT [[SMPS]]</div>Clownacyhttps://segaretro.org/index.php?title=Sound_Sorce&diff=962887Sound Sorce2024-02-26T13:25:53Z<p>Clownacy: Redirect to SMPS.</p>
<hr />
<div>#REDIRECT [[SMPS]]</div>Clownacyhttps://segaretro.org/index.php?title=Sound-Source&diff=962886Sound-Source2024-02-26T13:25:16Z<p>Clownacy: Redirect to SMPS.</p>
<hr />
<div>#REDIRECT [[SMPS]]</div>Clownacyhttps://segaretro.org/index.php?title=Sound_Source&diff=962885Sound Source2024-02-26T13:24:09Z<p>Clownacy: Redirect to SMPS.</p>
<hr />
<div>#REDIRECT [[SMPS]]</div>Clownacyhttps://segaretro.org/index.php?title=SMPS&diff=962813SMPS2024-02-26T01:16:35Z<p>Clownacy: Add a section on SMPS's naming.</p>
<hr />
<div>'''Sample Music Playback System''' ('''SMPS''') is the common name of a family of audio playback engines (or "drivers") and storage formats used by various [[Sega]] consoles (including the [[Sega Mega Drive]], [[Sega Mega-CD]], [[Sega 32X]], [[Sega Master System]] and [[Sega Game Gear]]). "SMPS" is thought to be a colloquial term - there is no evidence to suggest this was the naming scheme of any official drivers, but is the most widely accepted name for the system.<br />
<br />
Like other sound drivers, SMPS was designed as a means of processing audio information, allowing a console's CPU to communicate with sound chips on the board and create audible sound (i.e. "driving" the sound). It is usually associated with first-party Japanese Mega Drive games (where it was most predominantly used) - analogous to [[Sega of America]]'s use of the [[GEMS]] driver, and began appearing in games from the late 1980s until the aforementioned consoles bowed out of the market.<br />
<br />
By sharing drivers between games, developers could create tools to quickly produce audio, and it allows for music and sound effects to be more easily ported between games.<br />
<br />
==Variants==<br />
===Mega Drive and 32X===<br />
Mega Drive (and by extension, 32X) developers had a choice of which processor to run SMPS on; the 16-bit [[68000]], or the 8-bit [[Z80]]. The driver variants are known as '''SMPS 68000''' and '''SMPS Z80''' respectively.<br />
<br />
Some developers, such as [[Treasure]], chose to modify the driver, effectively making their own variants. Individual games such as ''[[Ristar]]'' also have their own modified drivers.<br />
<br />
====Source code====<br />
The source code to both SMPS-68000 and SMPS-Z80 was found and released by Hidden Palace in 2020[https://hiddenpalace.org/News/Sega_of_Japan_Sound_Documents_and_Source_Code]. The versions of the two drivers appear to be SMPS-68000 Type 1B and SMPS-Z80 Type 2 DAC.<br />
<br />
{{Download<br />
| title=SMPS-68000 source code<br />
| file=SMPS-68000_source_code.zip<br />
}}<br />
{{Download<br />
| title=SMPS-Z80 source code<br />
| file=SMPS-Z80_source_code.zip<br />
}}<br />
<br />
====Games which use SMPS 68000====<br />
=====Mega Drive=====<br />
{{SoundDriverList|SMPS 68000|MD}}<br />
<br />
=====32X=====<br />
{{SoundDriverList|SMPS 68000|32X}}<br />
<br />
====Games which use SMPS Z80====<br />
=====Mega Drive=====<br />
{{SoundDriverList|SMPS Z80|MD}}<br />
<br />
=====32X=====<br />
{{SoundDriverList|SMPS Z80|32X}}<br />
<br />
===Mega-CD===<br />
'''SMPS-PCM''' is variant of SMPS-68000 designed to work on the Mega-CD's second 68000 processor, giving it access to the system's [[RF5C164]] PCM chip.<br />
<br />
===Master System and Game Gear===<br />
SMPS drivers designed to work on the Z80 processors of the Master System and Game Gear were also produced. These tap into the two consoles' [[SN76489]] chip.<br />
<br />
===Pico===<br />
'''SMPS-Pico''' is a variant of SMPS-68000 that targets the Sega Pico. It plays audio using the [[SN76489]] and the Pico-specific [[UPD7759]] chip.<br />
<br />
The source code to this particular SMPS variant was released on AssemblerGames some time around 2016.<br />
<br />
{{Download<br />
| title=Sega Pico Dev Tools<br />
| file=SEGA_Pico_dev_tools.zip<br />
}}<br />
<br />
==Naming==<br />
The 'true' name of SMPS remains a subject of debate. Analysis of the source code reveals various possible names:<br />
<br />
{| prettytable" style="width:auto;<br />
! Name !! Usage<br />
|-<br />
| Sound<br />
| Appears frequently in documentation (m5_edit.jxw, ver11.doc, etc.). In the source code, this is the name of the label that marks the driver's entry point (m5cnt13.src, mdcnt11.asm).<br />
|-<br />
| Sound-Sorce<br />
| Appears in the header at the top of SMPS-Z80's source code files. Included with the source code is a [[wikipedia:sed|sed]] script that replaces the instances of this name with a parameter that is labelled 'game name'. This script was seemingly used on a handful of files, replacing 'Sound-Sorce' with 'MODEM_BOOT_ROM' and 'DICK_TRACY'.<br />
|-<br />
| Sound-Source<br />
| Appears in the header at the top of SMPS-68000's and SMPS-Pico's source code files. It is also the name used by some developers who had used SMPS back in the 90s[https://web.archive.org/web/20191006015702/https://twitter.com/Hikoshi_H/status/1180661206253596672][https://web.archive.org/web/20190920174036/https://twitter.com/Hikoshi_H/status/1169707879164608513][https://web.archive.org/web/20200719143541/https://twitter.com/Mazin__/status/105869176442331136]. Included with the source code is a sed script that replaces the instances of this name with a parameter that is labelled 'game name'.<br />
|-<br />
| Sound-Sample<br />
| Written on the SMPS-68000 and SMPS-Z80 source code's floppy disks. The SMPS-68000 source code has a Batch script (fmk.bat) that uses the aforementioned sed script to replace 'Sound-Source' with 'Sound-Sample'.<br />
|-<br />
| EASYSND<br />
| The name of the zip file that holds another zip file which contains the SMPS-Pico source code.<br />
|-<br />
| PICOSND<br />
| The name of the zip file which contains the SMPS-Pico source code. Also appears in various filenames and build scripts.<br />
|-<br />
| The PICO sound driver<br />
| Used by SMPS-Pico's GENERIC.MAK and PICOSND.MAK files.<br />
|}<br />
<br />
==Technical details==<br />
*[[SMPS/Headers|Headers]]<br />
*[[SMPS/Voices and samples|Voices and samples]]<br />
*[[SMPS/Song data|Song data]]<br />
<br />
==Tools==<br />
*[[xm4smps]]<br />
*[[xm3smps/oerg]] (official improved branch of [[xm3smps]])<br />
<br />
== External links ==<br />
*[http://gdri.smspower.org/wiki/index.php/Mega_Drive/Genesis_Sound_Engine_List A list of the sound engines used on the Mega Drive]<br />
<br />
==References==<br />
<references /><br />
[[Category:Mega Drive sound drivers]]<br />
[[Category:SMPS]]</div>Clownacyhttps://segaretro.org/index.php?title=SMPS&diff=962807SMPS2024-02-26T00:08:32Z<p>Clownacy: /* Source code */ Gah, dumb typo.</p>
<hr />
<div>'''Sample Music Playback System''' ('''SMPS''') is the common name of a family of audio playback engines (or "drivers") and storage formats used by various [[Sega]] consoles (including the [[Sega Mega Drive]], [[Sega Mega-CD]], [[Sega 32X]], [[Sega Master System]] and [[Sega Game Gear]]). "SMPS" is thought to be a colloquial term - there is no evidience to suggest this was the naming scheme of any official drivers, but is the most widely accepted name for the system.<br />
<br />
Like other sound drivers, SMPS was designed as a means of processing audio information, allowing a console's CPU to communicate with sound chips on the board and create audible sound (i.e. "driving" the sound). It is usually associated with first-party Japanese Mega Drive games (where it was most predominantly used) - analogous to [[Sega of America]]'s use of the [[GEMS]] driver, and began appearing in games from the late 1980s until the aforementioned consoles bowed out of the market.<br />
<br />
By sharing drivers between games, developers could create tools to quickly produce audio, and it allows for music and sound effects to be more easily ported between games.<br />
<br />
==Variants==<br />
===Mega Drive and 32X===<br />
Mega Drive (and by extension, 32X) developers had a choice of which processor to run SMPS on; the 16-bit [[68000]], or the 8-bit [[Z80]]. The driver variants are known as '''SMPS 68000''' and '''SMPS Z80''' respectively.<br />
<br />
Some developers, such as [[Treasure]], chose to modify the driver, effectively making their own variants. Individual games such as ''[[Ristar]]'' also have their own modified drivers.<br />
<br />
====Source code====<br />
The source code to both SMPS-68000 and SMPS-Z80 was found and released by Hidden Palace in 2020[https://hiddenpalace.org/News/Sega_of_Japan_Sound_Documents_and_Source_Code]. The versions of the two drivers appear to be SMPS-68000 Type 1B and SMPS-Z80 Type 2 DAC.<br />
<br />
{{Download<br />
| title=SMPS-68000 source code<br />
| file=SMPS-68000_source_code.zip<br />
}}<br />
{{Download<br />
| title=SMPS-Z80 source code<br />
| file=SMPS-Z80_source_code.zip<br />
}}<br />
<br />
====Games which use SMPS 68000====<br />
=====Mega Drive=====<br />
{{SoundDriverList|SMPS 68000|MD}}<br />
<br />
=====32X=====<br />
{{SoundDriverList|SMPS 68000|32X}}<br />
<br />
====Games which use SMPS Z80====<br />
=====Mega Drive=====<br />
{{SoundDriverList|SMPS Z80|MD}}<br />
<br />
=====32X=====<br />
{{SoundDriverList|SMPS Z80|32X}}<br />
<br />
===Mega-CD===<br />
'''SMPS-PCM''' is variant of SMPS-68000 designed to work on the Mega-CD's second 68000 processor, giving it access to the system's [[RF5C164]] PCM chip.<br />
<br />
===Master System and Game Gear===<br />
SMPS drivers designed to work on the Z80 processors of the Master System and Game Gear were also produced. These tap into the two consoles' [[SN76489]] chip.<br />
<br />
===Pico===<br />
'''SMPS-Pico''' is a variant of SMPS-68000 that targets the Sega Pico. It plays audio using the [[SN76489]] and the Pico-specific [[UPD7759]] chip.<br />
<br />
The source code to this particular SMPS variant was released on AssemblerGames some time around 2016.<br />
<br />
{{Download<br />
| title=Sega Pico Dev Tools<br />
| file=SEGA_Pico_dev_tools.zip<br />
}}<br />
<br />
==Technical details==<br />
*[[SMPS/Headers|Headers]]<br />
*[[SMPS/Voices and samples|Voices and samples]]<br />
*[[SMPS/Song data|Song data]]<br />
<br />
==Tools==<br />
*[[xm4smps]]<br />
*[[xm3smps/oerg]] (official improved branch of [[xm3smps]])<br />
<br />
== External links ==<br />
*[http://gdri.smspower.org/wiki/index.php/Mega_Drive/Genesis_Sound_Engine_List A list of the sound engines used on the Mega Drive]<br />
<br />
==References==<br />
<references /><br />
[[Category:Mega Drive sound drivers]]<br />
[[Category:SMPS]]</div>Clownacyhttps://segaretro.org/index.php?title=SMPS&diff=962806SMPS2024-02-26T00:07:49Z<p>Clownacy: /* Mega Drive and 32X */ Add information about the source code that was released in 2020.</p>
<hr />
<div>'''Sample Music Playback System''' ('''SMPS''') is the common name of a family of audio playback engines (or "drivers") and storage formats used by various [[Sega]] consoles (including the [[Sega Mega Drive]], [[Sega Mega-CD]], [[Sega 32X]], [[Sega Master System]] and [[Sega Game Gear]]). "SMPS" is thought to be a colloquial term - there is no evidience to suggest this was the naming scheme of any official drivers, but is the most widely accepted name for the system.<br />
<br />
Like other sound drivers, SMPS was designed as a means of processing audio information, allowing a console's CPU to communicate with sound chips on the board and create audible sound (i.e. "driving" the sound). It is usually associated with first-party Japanese Mega Drive games (where it was most predominantly used) - analogous to [[Sega of America]]'s use of the [[GEMS]] driver, and began appearing in games from the late 1980s until the aforementioned consoles bowed out of the market.<br />
<br />
By sharing drivers between games, developers could create tools to quickly produce audio, and it allows for music and sound effects to be more easily ported between games.<br />
<br />
==Variants==<br />
===Mega Drive and 32X===<br />
Mega Drive (and by extension, 32X) developers had a choice of which processor to run SMPS on; the 16-bit [[68000]], or the 8-bit [[Z80]]. The driver variants are known as '''SMPS 68000''' and '''SMPS Z80''' respectively.<br />
<br />
Some developers, such as [[Treasure]], chose to modify the driver, effectively making their own variants. Individual games such as ''[[Ristar]]'' also have their own modified drivers.<br />
<br />
====Source code====<br />
The source code to both SMPS-68000 and SMPS-Z80 were found and released by Hidden Palace in 2020[https://hiddenpalace.org/News/Sega_of_Japan_Sound_Documents_and_Source_Code]. The versions of the two drivers appear to be SMPS-68000 Type 1B and SMPS-Z80 Type 2 DAC.<br />
<br />
{{Download<br />
| title=SMPS-68000 source code<br />
| file=SMPS-68000_source_code.zip<br />
}}<br />
{{Download<br />
| title=SMPS-Z80 source code<br />
| file=SMPS-Z80_source_code.zip<br />
}}<br />
<br />
====Games which use SMPS 68000====<br />
=====Mega Drive=====<br />
{{SoundDriverList|SMPS 68000|MD}}<br />
<br />
=====32X=====<br />
{{SoundDriverList|SMPS 68000|32X}}<br />
<br />
====Games which use SMPS Z80====<br />
=====Mega Drive=====<br />
{{SoundDriverList|SMPS Z80|MD}}<br />
<br />
=====32X=====<br />
{{SoundDriverList|SMPS Z80|32X}}<br />
<br />
===Mega-CD===<br />
'''SMPS-PCM''' is variant of SMPS-68000 designed to work on the Mega-CD's second 68000 processor, giving it access to the system's [[RF5C164]] PCM chip.<br />
<br />
===Master System and Game Gear===<br />
SMPS drivers designed to work on the Z80 processors of the Master System and Game Gear were also produced. These tap into the two consoles' [[SN76489]] chip.<br />
<br />
===Pico===<br />
'''SMPS-Pico''' is a variant of SMPS-68000 that targets the Sega Pico. It plays audio using the [[SN76489]] and the Pico-specific [[UPD7759]] chip.<br />
<br />
The source code to this particular SMPS variant was released on AssemblerGames some time around 2016.<br />
<br />
{{Download<br />
| title=Sega Pico Dev Tools<br />
| file=SEGA_Pico_dev_tools.zip<br />
}}<br />
<br />
==Technical details==<br />
*[[SMPS/Headers|Headers]]<br />
*[[SMPS/Voices and samples|Voices and samples]]<br />
*[[SMPS/Song data|Song data]]<br />
<br />
==Tools==<br />
*[[xm4smps]]<br />
*[[xm3smps/oerg]] (official improved branch of [[xm3smps]])<br />
<br />
== External links ==<br />
*[http://gdri.smspower.org/wiki/index.php/Mega_Drive/Genesis_Sound_Engine_List A list of the sound engines used on the Mega Drive]<br />
<br />
==References==<br />
<references /><br />
[[Category:Mega Drive sound drivers]]<br />
[[Category:SMPS]]</div>Clownacyhttps://segaretro.org/index.php?title=File:SMPS-Z80_source_code.zip&diff=962805File:SMPS-Z80 source code.zip2024-02-26T00:05:31Z<p>Clownacy: Source code to SMPS Z80 (type 2 DAC?). Released by Hidden Palace in 2020.
https://hiddenpalace.org/News/Sega_of_Japan_Sound_Documents_and_Source_Code</p>
<hr />
<div>== Summary ==<br />
Source code to SMPS Z80 (type 2 DAC?). Released by Hidden Palace in 2020.<br />
https://hiddenpalace.org/News/Sega_of_Japan_Sound_Documents_and_Source_Code</div>Clownacyhttps://segaretro.org/index.php?title=File:SMPS-68000_source_code.zip&diff=962804File:SMPS-68000 source code.zip2024-02-26T00:04:36Z<p>Clownacy: Source code to SMPS 68000 (type 1b?). Released by Hidden Palace in 2020.
https://hiddenpalace.org/News/Sega_of_Japan_Sound_Documents_and_Source_Code</p>
<hr />
<div>== Summary ==<br />
Source code to SMPS 68000 (type 1b?). Released by Hidden Palace in 2020.<br />
https://hiddenpalace.org/News/Sega_of_Japan_Sound_Documents_and_Source_Code</div>Clownacyhttps://segaretro.org/index.php?title=SMPS&diff=962803SMPS2024-02-25T23:56:49Z<p>Clownacy: Added a section for the Sega Pico variant.</p>
<hr />
<div>'''Sample Music Playback System''' ('''SMPS''') is the common name of a family of audio playback engines (or "drivers") and storage formats used by various [[Sega]] consoles (including the [[Sega Mega Drive]], [[Sega Mega-CD]], [[Sega 32X]], [[Sega Master System]] and [[Sega Game Gear]]). "SMPS" is thought to be a colloquial term - there is no evidience to suggest this was the naming scheme of any official drivers, but is the most widely accepted name for the system.<br />
<br />
Like other sound drivers, SMPS was designed as a means of processing audio information, allowing a console's CPU to communicate with sound chips on the board and create audible sound (i.e. "driving" the sound). It is usually associated with first-party Japanese Mega Drive games (where it was most predominantly used) - analogous to [[Sega of America]]'s use of the [[GEMS]] driver, and began appearing in games from the late 1980s until the aforementioned consoles bowed out of the market.<br />
<br />
By sharing drivers between games, developers could create tools to quickly produce audio, and it allows for music and sound effects to be more easily ported between games.<br />
<br />
==Variants==<br />
===Mega Drive and 32X===<br />
Mega Drive (and by extension, 32X) developers had a choice of which processor to run SMPS on; the 16-bit [[68000]], or the 8-bit [[Z80]]. The driver variants are known as '''SMPS 68000''' and '''SMPS Z80''' respectively.<br />
<br />
Some developers, such as [[Treasure]], chose to modify the driver, effectively making their own variants. Individual games such as ''[[Ristar]]'' also have their own modified drivers.<br />
<br />
====Games which use SMPS 68000====<br />
=====Mega Drive=====<br />
{{SoundDriverList|SMPS 68000|MD}}<br />
<br />
=====32X=====<br />
{{SoundDriverList|SMPS 68000|32X}}<br />
<br />
====Games which use SMPS Z80====<br />
=====Mega Drive=====<br />
{{SoundDriverList|SMPS Z80|MD}}<br />
<br />
=====32X=====<br />
{{SoundDriverList|SMPS Z80|32X}}<br />
<br />
===Mega-CD===<br />
'''SMPS-PCM''' is variant of SMPS-68000 designed to work on the Mega-CD's second 68000 processor, giving it access to the system's [[RF5C164]] PCM chip.<br />
<br />
===Master System and Game Gear===<br />
SMPS drivers designed to work on the Z80 processors of the Master System and Game Gear were also produced. These tap into the two consoles' [[SN76489]] chip.<br />
<br />
===Pico===<br />
'''SMPS-Pico''' is a variant of SMPS-68000 that targets the Sega Pico. It plays audio using the [[SN76489]] and the Pico-specific [[UPD7759]] chip.<br />
<br />
The source code to this particular SMPS variant was released on AssemblerGames some time around 2016.<br />
<br />
{{Download<br />
| title=Sega Pico Dev Tools<br />
| file=SEGA_Pico_dev_tools.zip<br />
}}<br />
<br />
==Technical details==<br />
*[[SMPS/Headers|Headers]]<br />
*[[SMPS/Voices and samples|Voices and samples]]<br />
*[[SMPS/Song data|Song data]]<br />
<br />
==Tools==<br />
*[[xm4smps]]<br />
*[[xm3smps/oerg]] (official improved branch of [[xm3smps]])<br />
<br />
== External links ==<br />
*[http://gdri.smspower.org/wiki/index.php/Mega_Drive/Genesis_Sound_Engine_List A list of the sound engines used on the Mega Drive]<br />
<br />
==References==<br />
<references /><br />
[[Category:Mega Drive sound drivers]]<br />
[[Category:SMPS]]</div>Clownacyhttps://segaretro.org/index.php?title=File:SEGA_Pico_dev_tools.zip&diff=962802File:SEGA Pico dev tools.zip2024-02-25T23:56:24Z<p>Clownacy: Development tools for the Sega Pico. The original filename was 'SEGA Pico dev tools (Demon @ AssemblerGames).zip'. Contains the source code of SMPS-Pico, which is an SMPS-68000 derivative.</p>
<hr />
<div>== Summary ==<br />
Development tools for the Sega Pico. The original filename was 'SEGA Pico dev tools (Demon @ AssemblerGames).zip'. Contains the source code of SMPS-Pico, which is an SMPS-68000 derivative.</div>Clownacyhttps://segaretro.org/index.php?title=Jim_Power:_The_Arcade_Game&diff=962800Jim Power: The Arcade Game2024-02-25T23:12:36Z<p>Clownacy: /* Gameplay */ Added a missing space.</p>
<hr />
<div>{{UnreleasedBob<br />
| bobscreen=JimPowerTheArcadeGame title.png<br />
| publisher=[[Loriciel]]<br />
| developer=[[Loriciel]]<br />
| system=[[Sega Mega Drive]]<br />
| romsize=1MB (prototype)<br />
| sounddriver=[[A.U.D.I.O.S. Wave Slave MD]]<br />
| peripherals=<br />
| players=1<br />
| genre=Action<br />
| status=Prototype improperly dumped<br />
| date={{MissedRelease|MD|1993-11{{magref|videogamesus|58|51}}}}<br />
{{MissedRelease|MD|1994-02{{magref|mega|18|89}}}}<br />
{{MissedRelease|MD|1994-04{{magref|mega|20|81}}}}<br />
{{MissedRelease|MD|Spring 1994{{magref|segamagazin|4|11}}}}<br />
}}<br />
{{stub}}'''''Jim Power: The Arcade Game''''' is an unreleased [[Sega Mega Drive]] platform game developed by [[Loriciel]].<br />
<br />
==Gameplay==<br />
Despite its name, there was not an arcade release of ''Jim Power'' - it is in fact a re-tooled version of the 1993 Super NES/IBM PC game, ''Jim Power: The Lost Dimension in 3D'' (which itself is an update to the earlier 1992 release ''Jim Power In Mutant Planet'' for home computers).<br />
<br />
''The Arcade Game'' was planned to be essentially the same game as ''Lost Dimension in 3D'', however the stages utilising the Super NES' "Mode 7" effects were replaced with simpler 2D shoot-'em-up stages. There have also been numerous tweaks to make the game easier, as ''Jim Power'' games are notoriously difficult.<br />
<br />
The player controls Jim Power, where {{A}} makes him shoot, {{B}} makes him jump and {{C}} can wipe out all enemies on screen, provided you have enough bombs. There are a number of weapon upgrades too.<br />
<br />
The glaring omission from this Mega Drive port, and indeed most versions of the game, is the dropped support for [[wikipedia:anaglyph 3D|anaglyph 3D]] glasses, allowing the Super NES version to obtain a pseudo-3D look (and hence gain the name "''Lost Dimension in 3D''"; a pair is even included in the SNES version's box). Advertising and media coverage suggests that the feature was planned to appear in the Mega Drive game in some form, but it is unknown whether any compatible builds were created.<br />
<br />
==History==<br />
===Development===<br />
The game was cancelled in circa 1993-1994 due to Loriciel having financial troubles. However, a prototype surfaced on the internet, showing that ''Jim Power: The Arcade Game'' was very close to completion, despite the fact there is only one music track in the game, the one intended for stage 3, and the presence of placeholder ''[[Mega Turrican]]'' sound effects. All the levels can be played and the game can be beaten, but there is no proper ending sequence implemented in this build yet. <br />
<br />
In 2014, [[Piko Interactive]] made a licensing deal with Jim Power creator, Fernando Velez, acquiring rights and assets for the game{{Ref|https://pikointeractive.com/blog/jim-power-is-back-from-the-dead/}} in order to create a [[Nintendo Entertainment System|NES]] version from scratch. In the process, they also got ahold of a fully finished build of the unreleased Mega Drive version, with further plans to releasing it in a physical cartridge along with the brand new NES version and subsequent re-releases of the game. But due to the demise of Fernando Velez in 2016, plans had to be halted until 2019, when Piko finally managed to completely purchase the Jim Power intellectual property. A Kickstarter campaign was then set up in early 2020 to fund the production of different re-releases of the game, including the long lost Mega Drive version, which was finally released as ''[[Jim Power: The Lost Dimension in 3-D]]'' in 2021.<br />
<br />
In the US, the game was reportedly priced at $69.95{{magref|videogamesus|62|69}}.<br />
<br />
==Magazine articles==<br />
{{ratings|MD}}<br />
{{mainArticle|{{PAGENAME}}/Magazine articles}}<br />
<br />
==Promotional material==<br />
{{gallery<br />
|{{galleryPrintAd<br />
|gameplayers|0612|45<br />
|gamepro|54|267<br />
}}<br />
}}<br />
<br />
==ROM dump status==<br />
{{romtable|unreleased=yes|<br />
{{rom|MD|sha1=38adc1f792b06637e109d4b76fbfbf57623faf3b|size=1MB|date=1992-07|source=|comments=Has ''[[Street Smart]]'' header; apparently corrupt|quality=bad|prototype=yes|file=Jim Power The Arcade Game (prototype).7z}}<br />
}}<br />
<br />
==References==<br />
{{NECRetro|title=Jim Power in "Mutant Planet"|italics=yes}}<br />
<references /></div>Clownacyhttps://segaretro.org/index.php?title=Mdcomp&diff=962798Mdcomp2024-02-25T22:59:08Z<p>Clownacy: Add a link to the Windows shell extension.</p>
<hr />
<div>'''mdcomp''' (also known as '''FW-KENSC''') is a collection of software libraries and tools, made by [[User:Flamewing|Flamewing]], which implement compressors and decompressors for various Mega Drive-related formats. It is notable for achieving optimal compression of [[LZSS]]-based formats by leveraging graph theory, and also achieving near-optimal compression of the Nemesis format.<br />
<br />
== Overview ==<br />
mdcomp provides compressors and decompressors as a series of C++ classes, along with matching frontend programs, which are licensed under the terms of the LGPLv3. The frontend programs are to be used on the command line, and do not have a graphical interface. Also provided are several decompressors written in Motorola 68000 assembly, which are 0BSD-licensed.<br />
<br />
mdcomp purposefully avoids naïve data compression techniques, favouring compression ratio over compression speed and RAM usage. Its LZSS compressor computes a graph that represents each byte of the uncompressed data as a node, and each possible LZSS match as an edge which connects two nodes. Each edge is assigned a cost (the number of bits that it would cost to encode the match), and a [[wikipedia:shortest-path algorithms|shortest-path algorithm]] is used to determine the combination of matches which produces the smallest possible data, thus achieving optimal compression.<br />
<br />
== Supported formats ==<br />
* [[Kosinski compression|Kosinski]]<br />
* [[Kosinski+ compression|Kosinski+]]<br />
* [[Enigma compression|Enigma]]<br />
* [[Nemesis compression|Nemesis]]<br />
* [[Saxman compression|Saxman]]<br />
* [[Comper compression|Comper]]<br />
* [[ComperX compression|ComperX]]<br />
* [[Rocket compression|Rocket]]<br />
* [[SNKRLE compression|SNKRLE]]<br />
* [[LZKN1 compression|LZKN1]]<br />
<br />
== See also ==<br />
* [[KENS]]<br />
* [[KENSSharp]]<br />
<br />
== External links ==<br />
* [https://github.com/flamewing/mdcomp GitHub repository]<br />
* {{LinkRetro|topic=32235|title=Release thread}} at [[Sonic Retro]]<br />
* {{LinkRetro|topic=36252|title=Windows shell extension}}<br />
<br />
[[Category:Mega Drive Programs]]</div>Clownacyhttps://segaretro.org/index.php?title=Mdcomp&diff=962580Mdcomp2024-02-24T19:55:51Z<p>Clownacy: Fix a typo.</p>
<hr />
<div>'''mdcomp''' (also known as '''FW-KENSC''') is a collection of software libraries and tools, made by [[User:Flamewing|Flamewing]], which implement compressors and decompressors for various Mega Drive-related formats. It is notable for achieving optimal compression of [[LZSS]]-based formats by leveraging graph theory, and also achieving near-optimal compression of the Nemesis format.<br />
<br />
== Overview ==<br />
mdcomp provides compressors and decompressors as a series of C++ classes, along with matching frontend programs, which are licensed under the terms of the LGPLv3. The frontend programs are to be used on the command line, and do not have a graphical interface. Also provided are several decompressors written in Motorola 68000 assembly, which are 0BSD-licensed.<br />
<br />
mdcomp purposefully avoids naïve data compression techniques, favouring compression ratio over compression speed and RAM usage. Its LZSS compressor computes a graph that represents each byte of the uncompressed data as a node, and each possible LZSS match as an edge which connects two nodes. Each edge is assigned a cost (the number of bits that it would cost to encode the match), and a [[wikipedia:shortest-path algorithms|shortest-path algorithm]] is used to determine the combination of matches which produces the smallest possible data, thus achieving optimal compression.<br />
<br />
== Supported formats ==<br />
* [[Kosinski compression|Kosinski]]<br />
* [[Kosinski+ compression|Kosinski+]]<br />
* [[Enigma compression|Enigma]]<br />
* [[Nemesis compression|Nemesis]]<br />
* [[Saxman compression|Saxman]]<br />
* [[Comper compression|Comper]]<br />
* [[ComperX compression|ComperX]]<br />
* [[Rocket compression|Rocket]]<br />
* [[SNKRLE compression|SNKRLE]]<br />
* [[LZKN1 compression|LZKN1]]<br />
<br />
== See also ==<br />
* [[KENS]]<br />
* [[KENSSharp]]<br />
<br />
== External links ==<br />
* [https://github.com/flamewing/mdcomp GitHub repository]<br />
* {{LinkRetro|topic=32235|title=Release thread}} at [[Sonic Retro]]<br />
<br />
[[Category:Mega Drive Programs]]</div>Clownacyhttps://segaretro.org/index.php?title=KENSSharp&diff=962579KENSSharp2024-02-24T19:55:11Z<p>Clownacy: Added a link to KENS and mdcomp. Maybe there should be a 'compression libraries' category.</p>
<hr />
<div>'''KENSSharp''' is a cross-platform compression and decompression library by [[sonic:FraGag|FraGag]] written in C# for the .NET Framework 3.5 Client Profile and later. It is a port of [[KENS]], based on the design of the C++ port by [[sonic:flamewing|flamewing]]. KENSSharp is currently hosted on Sonic Retro's [[sonic:Community SVN Project|Community SVN Project]]. A front-end GUI application is also provided to compress and decompress individual files.<br />
<br />
==Downloads==<br />
{{Download<br />
|file=KensSharpFrontend.7z<br />
|filesize=54 KB<br />
|version=1.0 (revision 382)<br />
}}<br />
<br />
==See also==<br />
* [[The Sega Data Compressor]]<br />
* [[KENS]]<br />
* [[mdcomp]]<br />
<br />
==External links==<br />
{{LinkRetro|topic=24573|title=KENSSharp Release Thread}} at [[Sonic Retro]]<br />
<br />
[[Category:Mega Drive Programs]]</div>Clownacyhttps://segaretro.org/index.php?title=KENS&diff=962578KENS2024-02-24T19:54:08Z<p>Clownacy: Added a link to mdcomp. Maybe there should be a 'compression libraries' category.</p>
<hr />
<div>'''KENS''' (short for '''[[Kosinski compression|Kosinski]]''', '''[[Enigma compression|Enigma]]''', '''[[Nemesis compression|Nemesis]]''', and '''[[Saxman compression|Saxman]]''') is a software library that was originally created by Magus, which provides compressors and decompressors for the aforementioned four compression formats. [[The Sega Data Compressor]] is a frontend for KENS, which is also made by Magus.<br />
<br />
KENS is licensed under the LGPL v2.1 and distributed as a set of [[wikipedia:dynamic link libraries|dynamic link libraries]]. This is done to simplify the process of updating programs to newer versions of the library: being a collection of dynamically-linked binaries, only the DLL files need to be replaced, avoiding the need to modify or update the programs themselves.<br />
<br />
After the release of v1.4 RC1, in 2007, kram1024 officially provided an [[wikipedia:autotools|autotools]]-based version of KENS with cleaned-up code and command line tools. At that point, Magus retired from KENS development and handed control of the project over to kram1024.<br />
<br />
{{Multidownload<br />
| file1=KENS v1.4 RC3.7z<br />
| filename1=KENS v1.4 RC3<br />
| filesize1=64KB<br />
| file2=KENS v.1.4 RC3 (Source).zip<br />
| filename2=KENS v1.4 RC3 (Source)<br />
| filesize2=73KB<br />
}}<br />
<br />
==See also==<br />
* [[KENSSharp]]<br />
* [[mdcomp]]<br />
<br />
==External links==<br />
* {{LinkRetro|topic=3123|title=KENS release thread}} at [[Sonic Retro]]<br />
* [https://sourceforge.net/projects/genesiscomp/ SourceForge project]<br />
<br />
[[Category:Mega Drive Programs]]</div>Clownacyhttps://segaretro.org/index.php?title=Mdcomp&diff=962566Mdcomp2024-02-24T19:42:39Z<p>Clownacy: Created page with "'''mdcomp''' (also known as '''FW-KENSC''') is a collection of software libraries and tools, made by Flamewing, which implement compressors and decompressor..."</p>
<hr />
<div>'''mdcomp''' (also known as '''FW-KENSC''') is a collection of software libraries and tools, made by [[User:Flamewing|Flamewing]], which implement compressors and decompressors for various Mega Drive-related formats. It is notable for achieving optimal compression of [[LZSS]]-based formats by leveraging graph theory, and also achieving near-optimal compression of the Nemesis format.<br />
<br />
== Overview ==<br />
mdcomp provides compressors and decompressors as a series of C++ classes, along with matching frontend programs, which are licensed under the terms of the LGPLv3. The frontend programs are to be used on the command line, and do not have a graphical interface. Also provided are several decompressors written in Motorola 68000 assembly, which are 0BSD-licensed.<br />
<br />
mdcomp purposefully avoids naïve data compression techniques, favouring compression ratio over compression speed and RAM usage. Its LZSS compressor computes a graph that represents each byte of the uncompressed data as a node, and each possible LZSS match as an edge which connects two nodes. Each edge is assigned a cost (the number of bits that it would cost to encode the match), and a [[wikipedia:shortest-path algorithms|shortest-path algorithm]] is used to determine the combination of matches which produces the smallest possible data, thus achieving optimal compression.<br />
<br />
== Support formats ==<br />
* [[Kosinski compression|Kosinski]]<br />
* [[Kosinski+ compression|Kosinski+]]<br />
* [[Enigma compression|Enigma]]<br />
* [[Nemesis compression|Nemesis]]<br />
* [[Saxman compression|Saxman]]<br />
* [[Comper compression|Comper]]<br />
* [[ComperX compression|ComperX]]<br />
* [[Rocket compression|Rocket]]<br />
* [[SNKRLE compression|SNKRLE]]<br />
* [[LZKN1 compression|LZKN1]]<br />
<br />
== See also ==<br />
* [[KENS]]<br />
* [[KENSSharp]]<br />
<br />
== External links ==<br />
* [https://github.com/flamewing/mdcomp GitHub repository]<br />
* {{LinkRetro|topic=32235|title=Release thread}} at [[Sonic Retro]]<br />
<br />
[[Category:Mega Drive Programs]]</div>Clownacyhttps://segaretro.org/index.php?title=KENS&diff=962551KENS2024-02-24T18:51:51Z<p>Clownacy: Reworded much of the article to be more natural and removed irrelevant technical jargon and prospects which never came to be.</p>
<hr />
<div>'''KENS''' (short for '''[[Kosinski compression|Kosinski]]''', '''[[Enigma compression|Enigma]]''', '''[[Nemesis compression|Nemesis]]''', and '''[[Saxman compression|Saxman]]''') is a software library that was originally created by Magus, which provides compressors and decompressors for the aforementioned four compression formats. [[The Sega Data Compressor]] is a frontend for KENS, which is also made by Magus.<br />
<br />
KENS is licensed under the LGPL v2.1 and distributed as a set of [[wikipedia:dynamic link libraries|dynamic link libraries]]. This is done to simplify the process of updating programs to newer versions of the library: being a collection of dynamically-linked binaries, only the DLL files need to be replaced, avoiding the need to modify or update the programs themselves.<br />
<br />
After the release of v1.4 RC1, in 2007, kram1024 officially provided an [[wikipedia:autotools|autotools]]-based version of KENS with cleaned-up code and command line tools. At that point, Magus retired from KENS development and handed control of the project over to kram1024.<br />
<br />
{{Multidownload<br />
| file1=KENS v1.4 RC3.7z<br />
| filename1=KENS v1.4 RC3<br />
| filesize1=64KB<br />
| file2=KENS v.1.4 RC3 (Source).zip<br />
| filename2=KENS v1.4 RC3 (Source)<br />
| filesize2=73KB<br />
}}<br />
<br />
==See also==<br />
[[KENSSharp]]<br />
<br />
==External links==<br />
* {{LinkRetro|topic=3123|title=KENS release thread}} at [[Sonic Retro]]<br />
* [https://sourceforge.net/projects/genesiscomp/ SourceForge project]<br />
<br />
[[Category:Mega Drive Programs]]</div>Clownacyhttps://segaretro.org/index.php?title=Saxman_compression&diff=659401Saxman compression2021-03-20T20:49:36Z<p>Clownacy: /* Basic Format */ Explain zero-fills a bit better. Also, Saxman doesn't have an end-of-compression sequence: that's Kosinski.</p>
<hr />
<div>'''Saxman compression''' is the name given to the compression format used in the game ''[[Sonic the Hedgehog 2]]'' for the [[Sega Genesis|Sega Genesis/Mega Drive]]. Its name was given in honor of the person who cracked the format, [[sonic:User:Saxman|saxman]]. It is a variation of the [[LZSS]] algorithm.<br />
<br />
<br />
The two uses of Saxman compression in ''[[Sonic the Hedgehog 2]]'' are:<br />
* It is used to compress music data. In this case, the compressed data is prefixed with a small 2-byte header, listing the size of the compressed data in little-endian format.<br />
* It is used to compress the [[SMPS]] sound driver. In this case, the compressed data is not prefixed with a header - rather, the data's size is baked-into the decompressor's code.<br />
<br />
==Compression Theory==<br />
===Basic Format===<br />
<br />
The Saxman compression scheme is a basic implementation of LZSS, but with the quirk that dictionary matches can reference bytes beyond the start of the decompressed data. Such a match is called a 'zero fill', as the bytes it produces are all 00.<br />
<br />
The compressed data follows the following format:<br />
<br />
<pre><br />
AA BB BB .. AA BB BB ..<br />
</pre><br />
<br />
The A field is referred to as the description field. This is always 1 byte in length, starting at the beginning of the compressed data, and is followed by the B field, which is referred to as the data field. This goes on for as long as is necessary to cover all the data described in the description field. After that, the pattern repeats until the end of the compressed data is reached.<br />
<br />
===Description Field===<br />
<br />
The description field is made up of 8 bits in little endian bit (not byte) order, which means that the least significant bit is read first; in other words, each byte is read "backwards." So for example, if the description field is:<br />
<br />
<pre>FE</pre><br />
<br />
then the description field, in bits, in the correct order for interpretation, will be:<br />
<br />
<pre>[0111 1111]</pre><br />
<br />
Now, going from left to right, each bit is interpreted in the following way:<br />
<br />
* If the bit is a 1, it indicates uncompressed data.<br />
* If the bit is a 0, it indicates either a dictionary match or a zero fill.<br />
<br />
When the last bit from a description field is read, the corresponding command is processed normally. After it has finished being processed, if the file has not ended yet, then a new descriptor field will be read from the file. If the end of file is reached (as counted by number of bytes already read, compared to the size of compression data) and there are still description field bits left, they are ignored.<br />
<br />
===Uncompressed Data===<br />
<br />
If a 1 is read in the description field, the corresponding byte in the data field is already uncompressed and simply copied to the destination as-is.<br />
<br />
===Dictionary Match/Zero Fill===<br />
<br />
Dictionary matches and zero fills are both indicated by a 0 in the description field. The next 2 bytes will then form the offset and length: the format of these bytes is:<br />
<br />
<pre><br />
[LLLL LLLL] [HHHH CCCC]<br />
</pre><br />
<br />
The CCCC bits, plus 3, is the number of bytes to be copied (for dictionary matches) or the number of zeros to write (for zero fills). The remaining bits are used to form the position to copy from. Unlike what happens in ''normal'' LZSS or in '''[[Kosinski compression|Kosinski]]''', the offset is not completely relative in Saxman compression; instead, the position to copy from is computed based on the following pseudo-code:<br />
<br />
<pre><br />
base = ((%HHHHLLLLLLLL + $12) & $FFF) ; Combine everything into an address<br />
source = ((base - destination) & $FFF) + destination - $1000 ; Rebase it around destination<br />
</pre><br />
where "destination" is the relative address where data will be copied to (based on the start of the decoding buffer), and "source" is where data will be copied from in a dictionary match. The "base" address is an absolute address within the $1000-byte block obtained by stripping all but the high 4 bits of "destination"; it has to be ''rebased'' around "destination" as shown above to preserve the $1000-byte sliding window of the format. Whenever the resulting "source" address computed above is greater than the "destination" address in an unsigned comparison then, instead of copying bytes from the given location, the decoder will perform a zero fill instead. This can only happen due to integer overflow if "destination" is less than $1000 bytes and "base" ends up being more than "destination".<br />
<br />
Note: the Saxman/z80 decoder has only $800 bytes in its decompression buffer, so it does not rebase the address (nor does it need to); this means, however, that the decoder is simply unable to handle files that are longer than $1000 bytes when decompressed even if you give it a large enough decompression buffer to work with. In contrast, the Saxman/68k decoder does rebase it — but while the rebasing process is functionally equivalent to the pseudo-code given above, it is done in a different form which obscures what is happening.<br />
<br />
=== Examples ===<br />
<br />
====Zero Fill====<br />
<br />
The following Saxman/z80-compressed stream:<br />
<br />
<pre>03 00 00 00 FF</pre><br />
<br />
produces the following output:<br />
<br />
<pre>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</pre><br />
<br />
The first two bytes are the compressed data length, in Big endian order: that is, the compressed data is 3 bytes. The next byte is a description field: [0000 0000]. Reading the lowest bit first, we get a zero, indicating either a dictionary match or a zero fill; the next two bytes are the source address and length, and come out to a source position of $0F12 (computed as outlined above) and a length of $12. These flag a zero fill, since the source ($0F12) is after the destination ($0000), so we write $12 zeroes. When reading a new bit, we notice that all 3 bytes in the compressed data have been read, so decompression terminates.<br />
<br />
==Origin==<br />
Saxman is derived from [https://web.archive.org/web/19990203141013/http://oak.oakland.edu/pub/simtelnet/msdos/arcutils/lz_comp2.zip an LZSS implementation by Haruhiko Okumura], which dates back to the late 1980s. The two decompressors used by ''[[Sonic the Hedgehog 2]]'' are largely transcriptions of the original C code.<br />
<br />
Saxman bears one difference from Okumura's format: dictionary matches that point to before the start of the decompressed data produce 0x00 bytes, instead of the 0x20 bytes of the original.<br />
<br />
<br />
In order to convert Okumura's compressor/decompressor to support Saxman, both uses of the space ASCII character in LZSS.C must be changed to zero instead. To be more specific, these two lines...<br />
<br />
<br />
<pre> for (i = s; i < r; i++) text_buf[i] = ' '; /* Clear the buffer with<br />
any character that will appear often. */</pre><br />
<br />
<br />
<pre> for (i = 0; i < N - F; i++) text_buf[i] = ' ';</pre><br />
<br />
<br />
...must be changed to this:<br />
<br />
<br />
<pre> for (i = s; i < r; i++) text_buf[i] = 0; /* Clear the buffer with<br />
any character that will appear often. */</pre><br />
<br />
<br />
<pre> for (i = 0; i < N - F; i++) text_buf[i] = 0;</pre><br />
<br />
==Decompression code==<br />
<br />
An annotated version of the Saxman/z80 decompression code is provided below for reference. The code is taken from the ''[[Sonic the Hedgehog 2]]'' sound driver.<br />
<br />
<pre>;zsub_1271<br />
zSaxmanDec:<br />
exx<br />
ld bc,0<br />
ld de,0<br />
exx<br />
ld de,zMusicData<br />
ld c,(hl)<br />
inc hl<br />
ld b,(hl) ; bc = (hl) i.e. "size of song"<br />
inc hl<br />
ld (zGetNextByte+1),hl ; modify inst. @ zGetNextByte -- set to beginning of decompression stream<br />
inc bc<br />
ld (zDecEndOrGetByte+1),bc ; modify inst. @ zDecEndOrGetByte -- set to length of song, +1<br />
<br />
;zloc_1288<br />
zSaxmanReadLoop:<br />
<br />
exx ; shadow reg set<br />
srl c ; c >> 1 (active control byte)<br />
srl b ; b >> 1 (just a mask that lets us know when we need to reload)<br />
bit 0,b ; test next bit of 'b'<br />
jr nz,+ ; if it's set, we still have bits left in 'c'; jump to '+'<br />
; If you get here, we're out of bits in 'c'!<br />
call zDecEndOrGetByte ; get next byte -> 'a'<br />
ld c,a ; a -> 'c'<br />
ld b,0FFh ; b = FFh (8 new bits in 'c')<br />
+<br />
bit 0,c ; test next bit of 'c'<br />
exx ; normal reg set<br />
jr z,+ ; if bit not set, it's a compression bit; jump to '+'<br />
; If you get here, there's a non-compressed byte<br />
call zDecEndOrGetByte ; get next byte -> 'a' <br />
ld (de),a ; store it directly to the target memory address<br />
inc de ; de++<br />
exx ; shadow reg set<br />
inc de ; Also increase shadow-side 'de'... relative pointer only, does not point to output Z80_RAM<br />
exx ; normal reg set<br />
jr zSaxmanReadLoop ; loop back around...<br />
+<br />
call zDecEndOrGetByte ; get next byte -> 'a'<br />
ld c,a ; a -> 'c' (low byte of target address)<br />
call zDecEndOrGetByte ; get next byte -> 'a'<br />
ld b,a ; a -> 'b' (high byte of target address + count)<br />
and 0Fh ; keep only lower four bits...<br />
add a,3 ; add 3 (minimum 3 bytes are to be read in this mode)<br />
push af ; save 'a'...<br />
ld a,b ; b -> 'a' (low byte of target address)<br />
rlca<br />
rlca<br />
rlca<br />
rlca<br />
and 0Fh ; basically (b >> 4) & 0xF (upper four bits now exclusively as lower four bits)<br />
ld b,a ; a -> 'b' (only upper four bits of value make up part of the address)<br />
ld a,c <br />
add a,12h<br />
ld c,a<br />
adc a,b<br />
sub c<br />
and 0Fh<br />
ld b,a ; bc += 12h<br />
pop af ; restore 'a' (byte count to read; no less than 3)<br />
exx ; shadow reg set<br />
push de ; keep current 'de' (relative pointer) value...<br />
ld l,a ; how many bytes we will read -> 'hl'<br />
ld h,0<br />
add hl,de ; add current relative pointer...<br />
ex de,hl ; effectively, de += a<br />
exx ; normal reg set<br />
pop hl ; shadow 'de' -> 'hl' (relative pointer, prior to all bytes read, relative)<br />
or a ; Clear carry<br />
sbc hl,bc ; hl -= bc<br />
jr nc,+ ; if result positive, jump to '+'<br />
ex de,hl ; current output pointer -> 'hl'<br />
ld b,a ; how many bytes to load -> 'b'<br />
<br />
- ld (hl),0 ; fill in zeroes that many times<br />
inc hl<br />
djnz -<br />
<br />
ex de,hl ; output pointer updated<br />
jr zSaxmanReadLoop ; loop back around...<br />
+<br />
ld hl,zMusicData ; point at beginning of decompression point<br />
add hl,bc ; move ahead however many bytes<br />
ld c,a<br />
ld b,0<br />
ldir<br />
jr zSaxmanReadLoop<br />
; End of function zSaxmanDec<br />
<br />
<br />
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||<br />
<br />
<br />
; This is an ugly countdown to zero implemented in repeatedly modifying code!!<br />
; But basically, it starts at the full length of the song +1 (so it can decrement)<br />
; and waits until 'hl' decrements to zero<br />
;zsub_12E8<br />
zDecEndOrGetByte:<br />
ld hl,0 ; "self-modified code" -- starts at full length of song +1, waits until it gets to 1...<br />
dec hl ; ... where this will be zero<br />
ld (zDecEndOrGetByte+1),hl ; "self-modifying code" -- update the count in case it's not zero<br />
ld a,h <br />
or l<br />
jr z,+ ; If 'h' and 'l' both equal zero, we quit!!<br />
;zloc_12F3<br />
zGetNextByte:<br />
ld hl,0 ; "self-modified code" -- get address of next compressed byte<br />
ld a,(hl) ; put it into -> 'a'<br />
inc hl ; next byte...<br />
ld (zGetNextByte+1),hl ; change inst @ zGetNextByte so it loads next compressed byte<br />
ret ; still going...<br />
+<br />
pop hl ; throws away return address to this function call so that next 'ret' exits decompressor (we're done!)<br />
ret ; Exit decompressor<br />
; End of function zDecEndOrGetByte</pre><br />
<br />
[[Category:Data compression]]</div>Clownacyhttps://segaretro.org/index.php?title=Saxman_compression&diff=628271Saxman compression2020-10-06T23:00:51Z<p>Clownacy: /* Origin */ Turns out there's a much simpler way to make LZSS.c produce Saxman files</p>
<hr />
<div>'''Saxman compression''' is the name given to the compression format used in the game ''[[Sonic the Hedgehog 2]]'' for the [[Sega Genesis|Sega Genesis/Mega Drive]]. Its name was given in honor of the person who cracked the format, [[sonic:User:Saxman|saxman]]. It is a variation of the [[LZSS]] algorithm.<br />
<br />
<br />
The two uses of Saxman compression in ''[[Sonic the Hedgehog 2]]'' are:<br />
* It is used to compress music data. In this case, the compressed data is prefixed with a small 2-byte header, listing the size of the compressed data in little-endian format.<br />
* It is used to compress the [[SMPS]] sound driver. In this case, the compressed data is not prefixed with a header - rather, the data's size is baked-into the decompressor's code.<br />
<br />
==Compression Theory==<br />
===Basic Format===<br />
<br />
The Saxman compression scheme is a basic LZSS compression, but it has the additional capability of having a zero fill without having encountered any zeroes before.<br />
<br />
The compressed data follows the following format:<br />
<br />
<pre><br />
AA BB BB .. AA BB BB ..<br />
</pre><br />
<br />
The A field is referred to as the description field. This is always 1 byte in length, starting at the beginning of the compressed data, and is followed by the B field, which is referred to as the data field. This goes on for as long as is necessary to cover all the data described in the description field. After that, the pattern repeats until the end of compression sequence is encountered.<br />
<br />
===Description Field===<br />
<br />
The description field is made up of 8 bits in little endian bit (not byte) order, which means that the least significant bit is read first; in other words, each byte is read "backwards." So for example, if the description field is:<br />
<br />
<pre>FE</pre><br />
<br />
then the description field, in bits, in the correct order for interpretation, will be:<br />
<br />
<pre>[0111 1111]</pre><br />
<br />
Now, going from left to right, each bit is interpreted in the following way:<br />
<br />
* If the bit is a 1, it indicates uncompressed data.<br />
* If the bit is a 0, it indicates either a dictionary match or a zero fill.<br />
<br />
When the last bit from a description field is read, the corresponding command is processed normally. After it has finished being processed, if the file has not ended yet, then a new descriptor field will be read from the file. If the end of file is reached (as counted by number of bytes already read, compared to the size of compression data) and there are still description field bits left, they are ignored.<br />
<br />
===Uncompressed Data===<br />
<br />
If a 1 is read in the description field, the corresponding byte in the data field is already uncompressed and simply copied to the destination as-is.<br />
<br />
===Dictionary Match/Zero Fill===<br />
<br />
Dictionary matches and zero fills are both indicated by a 0 in the description field. The next 2 bytes will then form the offset and length: the format of these bytes is:<br />
<br />
<pre><br />
[LLLL LLLL] [HHHH CCCC]<br />
</pre><br />
<br />
The CCCC bits, plus 3, is the number of bytes to be copied (for dictionary matches) or the number of zeros to write (for zero fills). The remaining bits are used to form the position to copy from. Unlike what happens in ''normal'' LZSS or in '''[[Kosinski compression|Kosinski]]''', the offset is not completely relative in Saxman compression; instead, the position to copy from is computed based on the following pseudo-code:<br />
<br />
<pre><br />
base = ((%HHHHLLLLLLLL + $12) & $FFF) ; Combine everything into an address<br />
source = ((base - destination) & $FFF) + destination - $1000 ; Rebase it around destination<br />
</pre><br />
where "destination" is the relative address where data will be copied to (based on the start of the decoding buffer), and "source" is where data will be copied from in a dictionary match. The "base" address is an absolute address within the $1000-byte block obtained by stripping all but the high 4 bits of "destination"; it has to be ''rebased'' around "destination" as shown above to preserve the $1000-byte sliding window of the format. Whenever the resulting "source" address computed above is greater than the "destination" address in an unsigned comparison then, instead of copying bytes from the given location, the decoder will perform a zero fill instead. This can only happen due to integer overflow if "destination" is less than $1000 bytes and "base" ends up being more than "destination".<br />
<br />
Note: the Saxman/z80 decoder has only $800 bytes in its decompression buffer, so it does not rebase the address (nor does it need to); this means, however, that the decoder is simply unable to handle files that are longer than $1000 bytes when decompressed even if you give it a large enough decompression buffer to work with. In contrast, the Saxman/68k decoder does rebase it — but while the rebasing process is functionally equivalent to the pseudo-code given above, it is done in a different form which obscures what is happening.<br />
<br />
=== Examples ===<br />
<br />
====Zero Fill====<br />
<br />
The following Saxman/z80-compressed stream:<br />
<br />
<pre>03 00 00 00 FF</pre><br />
<br />
produces the following output:<br />
<br />
<pre>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</pre><br />
<br />
The first two bytes are the compressed data length, in Big endian order: that is, the compressed data is 3 bytes. The next byte is a description field: [0000 0000]. Reading the lowest bit first, we get a zero, indicating either a dictionary match or a zero fill; the next two bytes are the source address and length, and come out to a source position of $0F12 (computed as outlined above) and a length of $12. These flag a zero fill, since the source ($0F12) is after the destination ($0000), so we write $12 zeroes. When reading a new bit, we notice that all 3 bytes in the compressed data have been read, so decompression terminates.<br />
<br />
==Origin==<br />
Saxman is derived from [https://web.archive.org/web/19990203141013/http://oak.oakland.edu/pub/simtelnet/msdos/arcutils/lz_comp2.zip an LZSS implementation by Haruhiko Okumura], which dates back to the late 1980s. The two decompressors used by ''[[Sonic the Hedgehog 2]]'' are largely transcriptions of the original C code.<br />
<br />
Saxman bears one difference from Okumura's format: dictionary matches that point to before the start of the decompressed data produce 0x00 bytes, instead of the 0x20 bytes of the original.<br />
<br />
<br />
In order to convert Okumura's compressor/decompressor to support Saxman, both uses of the space ASCII character in LZSS.C must be changed to zero instead. To be more specific, these two lines...<br />
<br />
<br />
<pre> for (i = s; i < r; i++) text_buf[i] = ' '; /* Clear the buffer with<br />
any character that will appear often. */</pre><br />
<br />
<br />
<pre> for (i = 0; i < N - F; i++) text_buf[i] = ' ';</pre><br />
<br />
<br />
...must be changed to this:<br />
<br />
<br />
<pre> for (i = s; i < r; i++) text_buf[i] = 0; /* Clear the buffer with<br />
any character that will appear often. */</pre><br />
<br />
<br />
<pre> for (i = 0; i < N - F; i++) text_buf[i] = 0;</pre><br />
<br />
==Decompression code==<br />
<br />
An annotated version of the Saxman/z80 decompression code is provided below for reference. The code is taken from the ''[[Sonic the Hedgehog 2]]'' sound driver.<br />
<br />
<pre>;zsub_1271<br />
zSaxmanDec:<br />
exx<br />
ld bc,0<br />
ld de,0<br />
exx<br />
ld de,zMusicData<br />
ld c,(hl)<br />
inc hl<br />
ld b,(hl) ; bc = (hl) i.e. "size of song"<br />
inc hl<br />
ld (zGetNextByte+1),hl ; modify inst. @ zGetNextByte -- set to beginning of decompression stream<br />
inc bc<br />
ld (zDecEndOrGetByte+1),bc ; modify inst. @ zDecEndOrGetByte -- set to length of song, +1<br />
<br />
;zloc_1288<br />
zSaxmanReadLoop:<br />
<br />
exx ; shadow reg set<br />
srl c ; c >> 1 (active control byte)<br />
srl b ; b >> 1 (just a mask that lets us know when we need to reload)<br />
bit 0,b ; test next bit of 'b'<br />
jr nz,+ ; if it's set, we still have bits left in 'c'; jump to '+'<br />
; If you get here, we're out of bits in 'c'!<br />
call zDecEndOrGetByte ; get next byte -> 'a'<br />
ld c,a ; a -> 'c'<br />
ld b,0FFh ; b = FFh (8 new bits in 'c')<br />
+<br />
bit 0,c ; test next bit of 'c'<br />
exx ; normal reg set<br />
jr z,+ ; if bit not set, it's a compression bit; jump to '+'<br />
; If you get here, there's a non-compressed byte<br />
call zDecEndOrGetByte ; get next byte -> 'a' <br />
ld (de),a ; store it directly to the target memory address<br />
inc de ; de++<br />
exx ; shadow reg set<br />
inc de ; Also increase shadow-side 'de'... relative pointer only, does not point to output Z80_RAM<br />
exx ; normal reg set<br />
jr zSaxmanReadLoop ; loop back around...<br />
+<br />
call zDecEndOrGetByte ; get next byte -> 'a'<br />
ld c,a ; a -> 'c' (low byte of target address)<br />
call zDecEndOrGetByte ; get next byte -> 'a'<br />
ld b,a ; a -> 'b' (high byte of target address + count)<br />
and 0Fh ; keep only lower four bits...<br />
add a,3 ; add 3 (minimum 3 bytes are to be read in this mode)<br />
push af ; save 'a'...<br />
ld a,b ; b -> 'a' (low byte of target address)<br />
rlca<br />
rlca<br />
rlca<br />
rlca<br />
and 0Fh ; basically (b >> 4) & 0xF (upper four bits now exclusively as lower four bits)<br />
ld b,a ; a -> 'b' (only upper four bits of value make up part of the address)<br />
ld a,c <br />
add a,12h<br />
ld c,a<br />
adc a,b<br />
sub c<br />
and 0Fh<br />
ld b,a ; bc += 12h<br />
pop af ; restore 'a' (byte count to read; no less than 3)<br />
exx ; shadow reg set<br />
push de ; keep current 'de' (relative pointer) value...<br />
ld l,a ; how many bytes we will read -> 'hl'<br />
ld h,0<br />
add hl,de ; add current relative pointer...<br />
ex de,hl ; effectively, de += a<br />
exx ; normal reg set<br />
pop hl ; shadow 'de' -> 'hl' (relative pointer, prior to all bytes read, relative)<br />
or a ; Clear carry<br />
sbc hl,bc ; hl -= bc<br />
jr nc,+ ; if result positive, jump to '+'<br />
ex de,hl ; current output pointer -> 'hl'<br />
ld b,a ; how many bytes to load -> 'b'<br />
<br />
- ld (hl),0 ; fill in zeroes that many times<br />
inc hl<br />
djnz -<br />
<br />
ex de,hl ; output pointer updated<br />
jr zSaxmanReadLoop ; loop back around...<br />
+<br />
ld hl,zMusicData ; point at beginning of decompression point<br />
add hl,bc ; move ahead however many bytes<br />
ld c,a<br />
ld b,0<br />
ldir<br />
jr zSaxmanReadLoop<br />
; End of function zSaxmanDec<br />
<br />
<br />
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||<br />
<br />
<br />
; This is an ugly countdown to zero implemented in repeatedly modifying code!!<br />
; But basically, it starts at the full length of the song +1 (so it can decrement)<br />
; and waits until 'hl' decrements to zero<br />
;zsub_12E8<br />
zDecEndOrGetByte:<br />
ld hl,0 ; "self-modified code" -- starts at full length of song +1, waits until it gets to 1...<br />
dec hl ; ... where this will be zero<br />
ld (zDecEndOrGetByte+1),hl ; "self-modifying code" -- update the count in case it's not zero<br />
ld a,h <br />
or l<br />
jr z,+ ; If 'h' and 'l' both equal zero, we quit!!<br />
;zloc_12F3<br />
zGetNextByte:<br />
ld hl,0 ; "self-modified code" -- get address of next compressed byte<br />
ld a,(hl) ; put it into -> 'a'<br />
inc hl ; next byte...<br />
ld (zGetNextByte+1),hl ; change inst @ zGetNextByte so it loads next compressed byte<br />
ret ; still going...<br />
+<br />
pop hl ; throws away return address to this function call so that next 'ret' exits decompressor (we're done!)<br />
ret ; Exit decompressor<br />
; End of function zDecEndOrGetByte</pre><br />
<br />
[[Category:Data compression]]</div>Clownacyhttps://segaretro.org/index.php?title=Saxman_compression&diff=579132Saxman compression2020-04-20T16:42:37Z<p>Clownacy: Provide origin, fix a mistake (it's not big-endian), and do some cleanup</p>
<hr />
<div>'''Saxman compression''' is the name given to the compression format used in the game ''[[Sonic the Hedgehog 2]]'' for the [[Sega Genesis|Sega Genesis/Mega Drive]]. Its name was given in honor of the person who cracked the format, [[sonic:User:Saxman|saxman]]. It is a variation of the [[LZSS]] algorithm.<br />
<br />
<br />
The two uses of Saxman compression in ''[[Sonic the Hedgehog 2]]'' are:<br />
* It is used to compress music data. In this case, the compressed data is prefixed with a small 2-byte header, listing the size of the compressed data in little-endian format.<br />
* It is used to compress the [[SMPS]] sound driver. In this case, the compressed data is not prefixed with a header - rather, the data's size is baked-into the decompressor's code.<br />
<br />
==Compression Theory==<br />
===Basic Format===<br />
<br />
The Saxman compression scheme is a basic LZSS compression, but it has the additional capability of having a zero fill without having encountered any zeroes before.<br />
<br />
The compressed data follows the following format:<br />
<br />
<pre><br />
AA BB BB .. AA BB BB ..<br />
</pre><br />
<br />
The A field is referred to as the description field. This is always 1 byte in length, starting at the beginning of the compressed data, and is followed by the B field, which is referred to as the data field. This goes on for as long as is necessary to cover all the data described in the description field. After that, the pattern repeats until the end of compression sequence is encountered.<br />
<br />
===Description Field===<br />
<br />
The description field is made up of 8 bits in little endian bit (not byte) order, which means that the least significant bit is read first; in other words, each byte is read "backwards." So for example, if the description field is:<br />
<br />
<pre>FE</pre><br />
<br />
then the description field, in bits, in the correct order for interpretation, will be:<br />
<br />
<pre>[0111 1111]</pre><br />
<br />
Now, going from left to right, each bit is interpreted in the following way:<br />
<br />
* If the bit is a 1, it indicates uncompressed data.<br />
* If the bit is a 0, it indicates either a dictionary match or a zero fill.<br />
<br />
When the last bit from a description field is read, the corresponding command is processed normally. After it has finished being processed, if the file has not ended yet, then a new descriptor field will be read from the file. If the end of file is reached (as counted by number of bytes already read, compared to the size of compression data) and there are still description field bits left, they are ignored.<br />
<br />
===Uncompressed Data===<br />
<br />
If a 1 is read in the description field, the corresponding byte in the data field is already uncompressed and simply copied to the destination as-is.<br />
<br />
===Dictionary Match/Zero Fill===<br />
<br />
Dictionary matches and zero fills are both indicated by a 0 in the description field. The next 2 bytes will then form the offset and length: the format of these bytes is:<br />
<br />
<pre><br />
[LLLL LLLL] [HHHH CCCC]<br />
</pre><br />
<br />
The CCCC bits, plus 3, is the number of bytes to be copied (for dictionary matches) or the number of zeros to write (for zero fills). The remaining bits are used to form the position to copy from. Unlike what happens in ''normal'' LZSS or in '''[[Kosinski compression|Kosinski]]''', the offset is not completely relative in Saxman compression; instead, the position to copy from is computed based on the following pseudo-code:<br />
<br />
<pre><br />
base = ((%HHHHLLLLLLLL + $12) & $FFF) ; Combine everything into an address<br />
source = ((base - destination) & $FFF) + destination - $1000 ; Rebase it around destination<br />
</pre><br />
where "destination" is the relative address where data will be copied to (based on the start of the decoding buffer), and "source" is where data will be copied from in a dictionary match. The "base" address is an absolute address within the $1000-byte block obtained by stripping all but the high 4 bits of "destination"; it has to be ''rebased'' around "destination" as shown above to preserve the $1000-byte sliding window of the format. Whenever the resulting "source" address computed above is greater than the "destination" address in an unsigned comparison then, instead of copying bytes from the given location, the decoder will perform a zero fill instead. This can only happen due to integer overflow if "destination" is less than $1000 bytes and "base" ends up being more than "destination".<br />
<br />
Note: the Saxman/z80 decoder has only $800 bytes in its decompression buffer, so it does not rebase the address (nor does it need to); this means, however, that the decoder is simply unable to handle files that are longer than $1000 bytes when decompressed even if you give it a large enough decompression buffer to work with. In contrast, the Saxman/68k decoder does rebase it — but while the rebasing process is functionally equivalent to the pseudo-code given above, it is done in a different form which obscures what is happening.<br />
<br />
=== Examples ===<br />
<br />
====Zero Fill====<br />
<br />
The following Saxman/z80-compressed stream:<br />
<br />
<pre>03 00 00 00 FF</pre><br />
<br />
produces the following output:<br />
<br />
<pre>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</pre><br />
<br />
The first two bytes are the compressed data length, in Big endian order: that is, the compressed data is 3 bytes. The next byte is a description field: [0000 0000]. Reading the lowest bit first, we get a zero, indicating either a dictionary match or a zero fill; the next two bytes are the source address and length, and come out to a source position of $0F12 (computed as outlined above) and a length of $12. These flag a zero fill, since the source ($0F12) is after the destination ($0000), so we write $12 zeroes. When reading a new bit, we notice that all 3 bytes in the compressed data have been read, so decompression terminates.<br />
<br />
==Origin==<br />
Saxman is derived from [https://web.archive.org/web/19990203141013/http://oak.oakland.edu/pub/simtelnet/msdos/arcutils/lz_comp2.zip an LZSS implementation by Haruhiko Okumura], which dates back to the late 1980s. The two decompressors used by ''[[Sonic the Hedgehog 2]]'' are largely transcriptions of the original C code.<br />
<br />
<br />
Saxman bears one difference from Okumura's format: the addition of the aforementioned 'zero-fill' mode.<br />
<br />
In order to make the compressor produce zero-fill matches, the following modification must be made:<br />
<br />
<br />
<pre>void InsertNode(int r)<br />
/* Inserts string of length F, text_buf[r..r+F-1], into one of the<br />
trees (text_buf[r]'th tree) and returns the longest-match position<br />
and length via the global variables match_position and match_length.<br />
If match_length = F, then removes the old node in favor of the new<br />
one, because the old one will be deleted sooner.<br />
Note r plays double role, as tree node and position in buffer. */<br />
{<br />
int i, p, cmp;<br />
unsigned char *key;<br />
cmp = 1; key = &text_buf[r]; p = N + 1 + key[0];<br />
rson[r] = lson[r] = NIL; match_length = 0;<br />
for ( ; ; ) {<br />
if (cmp >= 0) {<br />
if (rson[p] != NIL) p = rson[p];<br />
else { rson[p] = r; dad[r] = p; return; }<br />
} else {<br />
if (lson[p] != NIL) p = lson[p];<br />
else { lson[p] = r; dad[r] = p; return; }<br />
}<br />
/* NEW CODE START */<br />
if (ftell(infile) < 0xFFF - THRESHOLD) {<br />
for (i = 0; i < F; i++)<br />
if ((cmp = key[i] - 0) != 0) break;<br />
if (i > match_length) {<br />
match_position = 0xFFF - F - THRESHOLD;<br />
if ((match_length = i) >= F) break;<br />
}<br />
}<br />
/* NEW CODE END */<br />
for (i = 1; i < F; i++)<br />
if ((cmp = key[i] - text_buf[p + i]) != 0) break;<br />
if (i > match_length) {<br />
match_position = p;<br />
if ((match_length = i) >= F) break;<br />
}<br />
}<br />
dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p];<br />
dad[lson[p]] = r; dad[rson[p]] = r;<br />
if (rson[dad[p]] == p) rson[dad[p]] = r;<br />
else lson[dad[p]] = r;<br />
dad[p] = NIL; /* remove p */<br />
}</pre><br />
<br />
==Decompression code==<br />
<br />
An annotated version of the Saxman/z80 decompression code is provided below for reference. The code is taken from the ''[[Sonic the Hedgehog 2]]'' sound driver.<br />
<br />
<pre>;zsub_1271<br />
zSaxmanDec:<br />
exx<br />
ld bc,0<br />
ld de,0<br />
exx<br />
ld de,zMusicData<br />
ld c,(hl)<br />
inc hl<br />
ld b,(hl) ; bc = (hl) i.e. "size of song"<br />
inc hl<br />
ld (zGetNextByte+1),hl ; modify inst. @ zGetNextByte -- set to beginning of decompression stream<br />
inc bc<br />
ld (zDecEndOrGetByte+1),bc ; modify inst. @ zDecEndOrGetByte -- set to length of song, +1<br />
<br />
;zloc_1288<br />
zSaxmanReadLoop:<br />
<br />
exx ; shadow reg set<br />
srl c ; c >> 1 (active control byte)<br />
srl b ; b >> 1 (just a mask that lets us know when we need to reload)<br />
bit 0,b ; test next bit of 'b'<br />
jr nz,+ ; if it's set, we still have bits left in 'c'; jump to '+'<br />
; If you get here, we're out of bits in 'c'!<br />
call zDecEndOrGetByte ; get next byte -> 'a'<br />
ld c,a ; a -> 'c'<br />
ld b,0FFh ; b = FFh (8 new bits in 'c')<br />
+<br />
bit 0,c ; test next bit of 'c'<br />
exx ; normal reg set<br />
jr z,+ ; if bit not set, it's a compression bit; jump to '+'<br />
; If you get here, there's a non-compressed byte<br />
call zDecEndOrGetByte ; get next byte -> 'a' <br />
ld (de),a ; store it directly to the target memory address<br />
inc de ; de++<br />
exx ; shadow reg set<br />
inc de ; Also increase shadow-side 'de'... relative pointer only, does not point to output Z80_RAM<br />
exx ; normal reg set<br />
jr zSaxmanReadLoop ; loop back around...<br />
+<br />
call zDecEndOrGetByte ; get next byte -> 'a'<br />
ld c,a ; a -> 'c' (low byte of target address)<br />
call zDecEndOrGetByte ; get next byte -> 'a'<br />
ld b,a ; a -> 'b' (high byte of target address + count)<br />
and 0Fh ; keep only lower four bits...<br />
add a,3 ; add 3 (minimum 3 bytes are to be read in this mode)<br />
push af ; save 'a'...<br />
ld a,b ; b -> 'a' (low byte of target address)<br />
rlca<br />
rlca<br />
rlca<br />
rlca<br />
and 0Fh ; basically (b >> 4) & 0xF (upper four bits now exclusively as lower four bits)<br />
ld b,a ; a -> 'b' (only upper four bits of value make up part of the address)<br />
ld a,c <br />
add a,12h<br />
ld c,a<br />
adc a,b<br />
sub c<br />
and 0Fh<br />
ld b,a ; bc += 12h<br />
pop af ; restore 'a' (byte count to read; no less than 3)<br />
exx ; shadow reg set<br />
push de ; keep current 'de' (relative pointer) value...<br />
ld l,a ; how many bytes we will read -> 'hl'<br />
ld h,0<br />
add hl,de ; add current relative pointer...<br />
ex de,hl ; effectively, de += a<br />
exx ; normal reg set<br />
pop hl ; shadow 'de' -> 'hl' (relative pointer, prior to all bytes read, relative)<br />
or a ; Clear carry<br />
sbc hl,bc ; hl -= bc<br />
jr nc,+ ; if result positive, jump to '+'<br />
ex de,hl ; current output pointer -> 'hl'<br />
ld b,a ; how many bytes to load -> 'b'<br />
<br />
- ld (hl),0 ; fill in zeroes that many times<br />
inc hl<br />
djnz -<br />
<br />
ex de,hl ; output pointer updated<br />
jr zSaxmanReadLoop ; loop back around...<br />
+<br />
ld hl,zMusicData ; point at beginning of decompression point<br />
add hl,bc ; move ahead however many bytes<br />
ld c,a<br />
ld b,0<br />
ldir<br />
jr zSaxmanReadLoop<br />
; End of function zSaxmanDec<br />
<br />
<br />
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||<br />
<br />
<br />
; This is an ugly countdown to zero implemented in repeatedly modifying code!!<br />
; But basically, it starts at the full length of the song +1 (so it can decrement)<br />
; and waits until 'hl' decrements to zero<br />
;zsub_12E8<br />
zDecEndOrGetByte:<br />
ld hl,0 ; "self-modified code" -- starts at full length of song +1, waits until it gets to 1...<br />
dec hl ; ... where this will be zero<br />
ld (zDecEndOrGetByte+1),hl ; "self-modifying code" -- update the count in case it's not zero<br />
ld a,h <br />
or l<br />
jr z,+ ; If 'h' and 'l' both equal zero, we quit!!<br />
;zloc_12F3<br />
zGetNextByte:<br />
ld hl,0 ; "self-modified code" -- get address of next compressed byte<br />
ld a,(hl) ; put it into -> 'a'<br />
inc hl ; next byte...<br />
ld (zGetNextByte+1),hl ; change inst @ zGetNextByte so it loads next compressed byte<br />
ret ; still going...<br />
+<br />
pop hl ; throws away return address to this function call so that next 'ret' exits decompressor (we're done!)<br />
ret ; Exit decompressor<br />
; End of function zDecEndOrGetByte</pre><br />
<br />
[[Category:Data compression]]</div>Clownacy