This commit is contained in:
ekeeke31 2007-08-18 11:16:32 +00:00
parent 12a6fd4170
commit d306c6576e
21 changed files with 148 additions and 5415 deletions

View File

@ -1,374 +0,0 @@
THE COMPLETE DOCUMENTATION ABOUT
GENESIS ROM FORMAT
Version 1.1
Release history
^^^^^^^^^^^^^^^
Version 1.0 (December, 1997)
- Initial Release
Version 1.1 (January, 1998)
- Splitted rom format explained!
- New company codes
- New errors in copyright interpreting found <sigh>
- Month interpreting (in copyright)
In this document you will find everything you need to know about
the information embedded within a Genesis ROM. You will also find
how to read all this information from the different ROM formats
(BIN, SMD and MD).
The information in this document was hacked by Volker Oth (dOnut)
and by me with help from technical documents found on internet.
The primary document from the internet that we used was gentech.txt.
If you want to change this document to add any important info about
the Genesis ROMs, do it freely but I would like to receive a copy of
the updated document. Then, I'll add your name in it and post it on my
homepage. Don't be a lamer and keep all names mentioned here!
Note that all numbers with a "H" in the left are in hexadecimal, and
the first byte of a file is the ZERO position. All information is
provided based on the BIN file-format because of the nature of this
format(see sections about each rom format).
*This document should be downloaded from my homepage. Any other site
may contain outdated material!*
If you use this information for anything, please give the proper
credits to the all these names listed below! I would thank you if you
include a link to our homepages and emails, too!
Felipe XnaK:
http://www.classicgaming.com/launchtool
felipe@ComPorts.com
Volker Oth (dOnut):
http://members.aol.com/~volkeroth
volkeroth@aol.com
THE BASIC INFORMATION:
^^^^^^^^^^^^^^^^^^^^^
H100: 'SEGA MEGA DRIVE' 1
H110: '(C)SEGA 1988.JUL' 2
H120: GAME NAME (DOMESTIC) 3
H150: GAME NAME (OVERSEAS) 4
H180: 'XX' 5
H182: 'XXXXXXX-XX' 6
H18E: XXXX 7
H190: 'XXXXXXXXXXXXXXXX' 8
H1A0: 00000000, XXXXXXXX 9
H1A8: RAM 10
H1BC: MODEM DATA 11
H1C8: MEMO 12
H1F0: Country in which the product 13
can be released.
1: This is just the console name. It can be 'SEGA MEGA DRIVE' or
'SEGA GENESIS' depending on the console's country of origin.
2: Copyright notice. There SHOULD be 4 characters for the company
code, a space and then the date in yyyy.mmm format; however, there are
variations.
For a listing of company codes, see "TABLE OF COMPANY CODES".
For a listing of month abbreviations, se "TABLE OF MONTH ABBREVIATIONS".
When the company uses a number as a company code, the copyright has
(in most cases!) this format: '(C)T-XX 1988.JUL', where XX is the
company code. If the company code has three digits, it should use the
space between the code and the date.
Some wrong copyrights i've found:
* The year is written as '199X' or '19XX', or doen't include the
millenium and the century.
* The company name is '00' or 'XX'
* Some companies that use a number for company code overwrite the
hiphen, not the space.
* Some companies doesn't include the '(C)' in the beginning and
others include just their name; some just include the the year
* Some copyrights have the year and month separated by ',','/', '-',
space or null character (H00). I'd found one that hasn't any separator
at all!
-- Good luck! --
3: This is the so-called "Domestic game name". Is the name the game has
in its country of origin. This field is 48 bytes long...
4: ... and this is the so-called "Overseas game name". This is the name
the game has worldwide. 48 bytes long too.
5: Type of product. This is 2 bytes long. Known values:
GM = Game
Al = Education
6: Product code and Version number:
* The first 7 characters are the product code
* The 2 characters after the hiphen is the version number. This will
vary depending on the the type of ROM or software version
7: Check sum, a two-bytes value (see "Calculating the Checksum")
8: I/0 support: (this is 16 bytes long)
J = Joypad 4 = Team Play
6 = 6-button Joypad 0 = Joystick for MS
K = Keyboard R = Serial RS232C
P = Printer T = Tablet
B = Control Ball V = Paddle Controller
F = Floppy Disk Drive C = CD-ROM
L = Activator M = Mega Mouse
9: ROM capacity. Here you will find the start and end address of the rom,
respectively. The start address in most cases is 0 and the end address is
the size of rom in BYTES. Note that these values don't include the headers
that some rom images have (discussed later). Each address is 4-bytes long.
10: There is a lot of information here that I can't help you with. What
I can say is that you can get the start and end positions of the backup
RAM at offset H1B4. Like in ROM addresses, you first acquire the start,
then the end address. Remember, these addresses are four bytes each.
11: If the rom has no support for MODEM, fill this with spaces. If it has
support for MODEM, then fill in this format: 'MOxxxxyy.z', where:
xxxx Firm name the same as in 2
yy MODEM NO.
z Version
12: I don't know what the heck it is! But by it's name and considering
all roms that I investigated, it seems that you can write whatever you want
in this field...
13: Countries where the game can be released. What is most interesting
here is that changing this info in some games has different behaviour.
Streets of Rage, for example, automatically changes it's name for Bare
Knuckle if you set the game for Japan. The "official" codes are:
E = Europe
J = Japan
U = USA
I've found some others as well(I do not guarantee this is correct!)
A = Asia
B = Brazil
4 = Brazil
F = France
8 = Hong Kong
This field can only contain three countries. This isn't really a
problem because all "unofficial" codes run as Europe! Don't forget to
set spaces to fill the bytes you don't use in this field.
TABLE OF COMPANY CODES:
^^^^^^^^^^^^^^^^^^^^^^
This table was compiled by myself by just getting the company code
in the ROM and writing the license that appears on the tittle screen.
In other words, it probably contains errors and is missing a lot of
companies.
When two comp1anies use the same code and are different companies
(at least to my knownledge) the names are separeted by an "or". If the
companies are the same (like Acclain and Flying Edge), they're separated
by a backslash (/).
CODE COMPANY
ACLD Ballistic
ASCI Asciiware
RSI Razorsoft
SEGA SEGA
TREC Treco
TmEE Tiido's Micro Electronical Entertainment Company
VRGN Virgin Games
WSTN Westone
10 Takara
11 Taito or Accolade
12 Capcom
13 Data East
14 Namco or Tengen
15 Sunsoft
16 Bandai
17 Dempa
18 Technosoft
19 Technosoft
20 Asmik
22 Micronet
23 Vic Tokai
24 American Sammy
29 Kyugo
32 Wolfteam
33 Kaneko
35 Toaplan
36 Tecmo
40 Toaplan
42 UFL Company Limited
43 Human
45 Game Arts
47 Sage's Creation
48 Tengen
49 Renovation or Telenet
50 Eletronic Arts
56 Razorsoft
58 Mentrix
60 Victor Musical Industries
69 Arena
70 Virgin
73 Soft Vision
74 Palsoft
76 Koei
79 U.S. Gold
81 Acclaim/Flying Edge
83 Gametek
86 Absolute
93 Sony
95 Konami
97 Tradewest
100 T*HQ Software
101 Tecmagik
112 Designer Software
113 Psygnosis
119 Accolade
120 Code Masters
125 Interplay
130 Activision
132 Shiny & Playmates
144 Atlus
151 Infogrames
161 Fox Interactive
239 Disney Interactive
- SPECIAL CASES:
In "Smurfs II" the copyright is just '(C) INFOGRAMES'
In "Baby's day out" rom, the copyright is: '(C) T-SNK 95-FEB',
but the company name is "HI-TECH entertainment" <sigh>
TABLE OF MONTH ABBREVIATIONS:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ABBREVIATIONS MONTH
JAN January
FEB February
MAR March
APR or APL April
MAY May
JUN June
JUL July
AUG or 08 August
SEP or SEPT September
OCT October
NOV November
DEC December
CALCULATING THE CHECKSUM:
^^^^^^^^^^^^^^^^^^^^^^^^
Genesis checksum is simple enough... All you need to do is:
1) Checksum starts as zero
2) Skip the first 512 bytes of the ROM
3) Read a byte from the rom and multiply its ascii value by 256, then sum
it to the checksum
4) Read the next byte from the rom and just sum it to the checksum
5) If you're not in the end of file, goto step 3
6) Get the first 16 bits from the resulting checksum and discard the higher
bits
7) That's your checksum!
Super Magic Drive Binary file-format (.BIN):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This rom file-format is a simple rom dump. Nothing more to add!
Super Magic Drive Interleaved file-format (.SMD):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is a much more complex file-format. It have a 512 bytes header
and is interleaved in 16KB blocks. These blocks have their even bytes
at the beginning and the odd bytes at the end of them.
WHAT YOU FIND IN THE 512 BYTES HEADER:
0: Number of blocks 1
1: H03 *
2: SPLIT? 2
8: HAA *
9: HBB *
ALL OTHER BYTES: H00
1: This first byte should have the number of 16KB blocks the rom has.
The header isn't part of the formula, so this number is:
[size of rom-512]/16386
If the size is more than 255, the value should be H00.
2: This byte indicates if the ROM is a part of a splitted rom series. If
the rom is the last part of the series (or isn't a splitted rom at all),
this byte should be H00. In other cases should be H40. See "CREATING
SPLITTED ROMS" for details on this format.
*: Fixed values
THE DE-INTERLEAVING CODE (how to convert a SMD to a BIN):
1) Skip the 512 bytes header
2) Get 16KB from the ROM (16384 bytes)
3) Decode the block
4) Write the decoded block to the BIN file
DECODING A SMD BLOCK (stating byte is 0):
1) Get Middlepoint (8192)
2) Get a byte from the block
3) If the byte position is equal or smaller than middlepoint, put it
in the first unused EVEN position of the decoded buffer
4) If the byte position is greater than middlepoint, put it in the
first unused ODD position of the decoded buffer
To convert a BIN to a SMD, just create a header (as explained before) and
then do the reverse process!
Multi Game Doctor file-format (.MD):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The MD file format also doesn't have a header. The interleaving it uses
is equal to the SMD, but without the division in blocks! (Even bytes in
the end of file, odd bytes in the beginning).
THE DECODING A MD (how to convert a MD to a BIN):
1) Get middlepoint ([size of rom]/2)
2) Get a byte from the ROM
3) If the byte position is equal or smaller than the middlepoint put the
byte in [byte position]*2 of the destination buffer
4) If the byte position is greater than the middlepoint, put the byte in
([byte position]*2) - [size of rom] -1
CREATING SPLITTED ROMS:
^^^^^^^^^^^^^^^^^^^^^^^
Splitted ROMs are a SMD divided into pieces. Knowing this, you may
guess that you first need to convert your ROM to a SMD! :)
To have a splitted ROM created all you need is divide your SMD in
several pieces, usually all with the same size (with the exception of
the last one). After doing that, you need to add a SMD header to all
these pieces. About these SMD headers:
1) The number of blocks embedded in them should be relative to the
piece, not to the joined ROM.
2) As stated before, with the exception of the last piece, all roms
should have their SPLIT byte set.
HOW YOU CAN HELP ME WITH THIS DOCUMENT:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Telling me the intricacies of a MGD ROM image. I never found one, but
I do believe it's equal to MD format.
- I'm trying to find out how the sprites are saved in Genesis ROMs. If
you have this info, I would like to have it!
- I never had a rom with modem support. If you have one, please test if
the information about it is correct in this documentation (I got it from
gentech). If you find it's correct, please explain me!!!
If you have any of this information, send it with your addresses (e-mail,
homepage, etc) so I can add this to the document!

View File

@ -1,74 +0,0 @@
REALTEC Cart Mapper - description v1 (2005.03.08)
by Tasco Deluxe [tascoDLX(AT)hotmail(DOT)com]
* Thanks to Mask Of Destiny for info about the boot state (from "The Earth Defend")
The REALTEC cart mapper is found in unlicensed Genesis/MegaDrive game carts produced by REALTEC.
Game carts known to utilize the mapper include "The Earth Defend", "Whac-A-Critter", and
"Funnyworld/Balloon Boy 2-in-1". They all contain common code used to display the REALTEC logo
and map a portion of the main ROM.
When the cart is powered on, 8KB of boot code is mapped by default into the cart's ROM area and
is mirrored throughout. This boot code is likely the last 8KB of the main ROM (all known carts
are 4 Mbit [512KB] w/ boot code at $07E000). The boot code, after displaying the REALTEC logo,
has the option to display a menu for game selection. After a selection is made, any neccessary
initializations are performed and a portion of the main ROM is mapped.
The code used to access the mapping registers is common amongst all known carts. A portion
of code is copied to RAM and executed. This code writes to the mapping registers based on a
selection number. Afterwards, the code clears the first 16 bytes of the I/O area ($A10000
thru $A1000F) and resets the M68000 manually (stack address is read from $000000, code address
is read from $000004).
The mapping is performed by writing to 3 mapped-in registers -- $400000, $402000, $404000.
Only one value is written per register. However, the same value is written 256 times in a row.
It is unknown whether this is because the registers explicitly require 256 writes, or because
the hardware is so crappy as to need multiple writes.
The register descriptions below are listed in the order they are commonly written.
All registers are byte-sized and only known to have write access.
* $402000 - Size of ROM range to map (in 1Mbit [128KB] blocks)
[maximum (theoretical) value of 32]
* $400000 - Bits of the ROM address (lower)
The bits (as written) are: ? ? ? ? ? c c c
* $404000 - Bits of the ROM address (upper)
The bits (as written) are: ? ? ? ? ? m m !
'?' is an unknown bit that is clear (in all known cases)
'!' is an unknown bit that is set (in all known cases)
From the above registers, the resulting ROM address (binary) is:
00mm ccc0 0000 0000 0000 0000
The common code in all REALTEC mapper carts sets the mapper values based on a selection number
(ROM address only -- the ROM size is fixed). The ROM addresses for these selections, numbered
1 thru 8, are:
1) $000000 [$00,$01]
2) $040000 [$02,$01]
3) $100000 [$00,$03]
4) $180000 [$04,$03]
5) $200000 [$00,$05]
6) $280000 [$04,$05]
7) $300000 [$00,$07]
8) $380000 [$04,$07]
The only cart known to use a selection other than #1 is "Funnyworld/Balloon Boy 2-in-1"
("Balloon Boy" is #1, "Funnyworld" is #2). It is assumed that the included code is merely a
suggestion and that any valid ROM address can be mapped.
A ROM range that is mapped, in order to function properly, must include a M68000 vector table
since the cart's entire ROM area is replaced by the mapped range. None of the known carts
attempt to remap a different ROM range after the boot code has executed. It is unknown whether
the mapper allows the boot code to be remapped, although it seems doubtful.

View File

@ -1,235 +0,0 @@
<HTML>
<HEAD>
<TITLE>GameGenie patches</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FEFEF4">
<BASEFONT FACE="MS Sans Serif" SIZE="-1">
<BR>
<CENTER><H1>GameGenie Patching</H1></CENTER>
<BR>
<P>&nbsp;&nbsp;GameGenie was a device created by codemasters and galoob that
let you make cheats for games. It was plugged in the console like a normal
cartridge, and in its top the desired cartridge was plugged. These cheats are
possible because what GameGenie do is edit the RAM that stores values used by
the ROMs, setting these values to a constant that can be, for example, the
number of lifes you have!</P>
<P>&nbsp;&nbsp;Genecyst was the first Genesis emulator to have support
for GameGenie then, with Kgen98, Steve Snake started to use this neat feature
in his great emulator. No ROM image of a GameGenie is necessary, as some may
imagine, to use them with console emulators, these programs themselves have a
built-in feature that acts like a GameGenie, writing the codes in the emulated
RAM.</P>
<P>&nbsp;&nbsp;The GameGenie code consists of a eight-bytes long string, and
the valid characters are A, B, C, D, E, F, G, H, J, K, L, M, N, P, R, S, T, V,
W, X, Y, Z, 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9, all in uppercase. Each character
have a binary repressentation, which is 5-bits long.</P>
<TABLE WIDTH="70%" BORDER="0" ALIGN="CENTER">
<TR>
<TD>
<TABLE BORDER="1" ALIGN="CENTER">
<TR>
<TH>Char</TH>
<TH>Value</TH>
</TR>
<TR>
<TD ALIGN="CENTER">A</TD><TD>00000</TD>
</TR>
<TR>
<TD ALIGN="CENTER">B</TD><TD>00001</TD>
</TR>
<TR>
<TD ALIGN="CENTER">C</TD><TD>00010</TD>
</TR>
<TR>
<TD ALIGN="CENTER">D</TD><TD>00011</TD>
</TR>
<TR>
<TD ALIGN="CENTER">E</TD><TD>00100</TD>
</TR>
<TR>
<TD ALIGN="CENTER">F</TD><TD>00101</TD>
</TR>
<TR>
<TD ALIGN="CENTER">G</TD><TD>00110</TD>
</TR>
<TR>
<TD ALIGN="CENTER">H</TD><TD>00111</TD>
</TR>
<TR>
<TD ALIGN="CENTER">J</TD><TD>01000</TD>
</TR>
<TR>
<TD ALIGN="CENTER">K</TD><TD>01001</TD>
</TR>
<TR>
<TD ALIGN="CENTER">L</TD><TD>01010</TD>
</TR>
</TABLE>
</TD>
<TD VALIGN="TOP">
<TABLE BORDER="1" ALIGN="CENTER">
<TR>
<TH>Char</TH>
<TH>Value</TH>
</TR>
<TR>
<TD ALIGN="CENTER">M</TD><TD>01011</TD>
</TR>
<TR>
<TD ALIGN="CENTER">N</TD><TD>01100</TD>
</TR>
<TR>
<TD ALIGN="CENTER">P</TD><TD>01101</TD>
</TR>
<TR>
<TD ALIGN="CENTER">R</TD><TD>01110</TD>
</TR>
<TR>
<TD ALIGN="CENTER">S</TD><TD>01111</TD>
</TR>
<TR>
<TD ALIGN="CENTER">T</TD><TD>10000</TD>
</TR>
<TR>
<TD ALIGN="CENTER">V</TD><TD>10001</TD>
</TR>
<TR>
<TD ALIGN="CENTER">W</TD><TD>10010</TD>
</TR>
<TR>
<TD ALIGN="CENTER">X</TD><TD>10011</TD>
</TR>
<TR>
<TD ALIGN="CENTER">Y</TD><TD>10100</TD>
</TR>
<TR>
<TD ALIGN="CENTER">Z</TD><TD>10101</TD>
</TR>
</TABLE>
</TD>
<TD VALIGN="TOP">
<TABLE BORDER="1" ALIGN="CENTER">
<TR>
<TH>Char</TH>
<TH>Value</TH>
</TR>
<TR>
<TD ALIGN="CENTER">0</TD><TD>10110</TD>
</TR>
<TR>
<TD ALIGN="CENTER">1</TD><TD>10111</TD>
</TR>
<TR>
<TD ALIGN="CENTER">2</TD><TD>11000</TD>
</TR>
<TR>
<TD ALIGN="CENTER">3</TD><TD>11001</TD>
</TR>
<TR>
<TD ALIGN="CENTER">4</TD><TD>11010</TD>
</TR>
<TR>
<TD ALIGN="CENTER">5</TD><TD>11011</TD>
</TR>
<TR>
<TD ALIGN="CENTER">6</TD><TD>11100</TD>
</TR>
<TR>
<TD ALIGN="CENTER">7</TD><TD>11101</TD>
</TR>
<TR>
<TD ALIGN="CENTER">8</TD><TD>11110</TD>
</TR>
<TR>
<TD ALIGN="CENTER">9</TD><TD>11111</TD>
</TR>
</TABLE>
</TD>
</TR>
</TABLE>
<BR>
<P>&nbsp;&nbsp;The cheat code should be firstly converted directly using the
table above, and then the bits should be reordered. For example, the GameGenie
code SCRA-BJX0 is translated to:</P>
<FONT FACE="Courier">
<TABLE BORDER="0" ALIGN="CENTER">
<TR>
<TD>
<TABLE BORDER="0" ALIGN="CENTER">
<TR><TD ALIGN="RIGHT" VALIGN="MIDDLE">Code:</TD></TR>
<TR><TD ALIGN="RIGHT" VALIGN="MIDDLE">Bits:</TD></TR>
<TR><TD ALIGN="RIGHT" VALIGN="MIDDLE">Id:</TD></TR>
</TABLE>
</TD>
<TD>
<TABLE BORDER="1" ALIGN="CENTER">
<TR ALIGN="CENTER">
<TD>S</TD><TD>C</TD><TD>R</TD><TD>A</TD>
</TR>
<TR ALIGN="CENTER">
<TD>01111</TD><TD>00010</TD><TD>01110</TD><TD>00000</TD>
</TR>
<TR ALIGN="CENTER">
<TD>ijklm</TD><TD>nopIJ</TD><TD>KLMNO</TD><TD>PABCD</TD>
</TR>
</TABLE>
</TD>
<TD>
<TABLE BORDER="0" ALIGN="CENTER">
<TR><TD ALIGN="RIGHT" VALIGN="MIDDLE">-</TD></TR>
<TR><TD ALIGN="RIGHT" VALIGN="MIDDLE">-</TD></TR>
<TR><TD ALIGN="RIGHT" VALIGN="MIDDLE">-</TD></TR>
</TABLE>
</TD>
<TD>
<TABLE BORDER="1" ALIGN="CENTER">
<TR ALIGN="CENTER"><TD>B</TD><TD>J</TD><TD>X</TD><TD>0</TD></TR>
<TR ALIGN="CENTER"><TD>00001</TD><TD>01000</TD><TD>10011</TD><TD>10110</TD></TR>
<TR ALIGN="CENTER"><TD>EFGHd</TD><TD>efgha</TD><TD>bcQRS</TD><TD>TUVWX</TD></TR>
</TABLE>
</TD>
</TR>
</TABLE>
</FONT>
<P>&nbsp;&nbsp;Then rearrange (using the id) as...</P>
<FONT FACE="Courier">
<TABLE BORDER="0" ALIGN="CENTER">
<TR>
<TD>
<TABLE BORDER="0" ALIGN="CENTER">
<TR><TD ALIGN="RIGHT" VALIGN="MIDDLE">Bits:</TD></TR>
<TR><TD ALIGN="RIGHT" VALIGN="MIDDLE">Id:</TD></TR>
</TABLE>
</TD>
<TD>
<TABLE BORDER="1" ALIGN="CENTER">
<TR>
<TD>00000000</TD><TD>10011100</TD><TD>01110110</TD>
</TR>
<TR ALIGN="CENTER">
<TD>ABCDEFGH</TD><TD>IJKLMNOP</TD><TD>QRSTUVWX</TD>
</TR>
</TABLE>
</TD>
<TD>
<TABLE BORDER="0" ALIGN="CENTER">
<TR><TD ALIGN="RIGHT" VALIGN="MIDDLE">:</TD></TR>
<TR><TD ALIGN="RIGHT" VALIGN="MIDDLE">:</TD></TR>
</TABLE>
</TD>
<TD>
<TABLE BORDER="1">
<TR ALIGN="CENTER"><TD>01010100</TD> <TD>01111000</TD></TR>
<TR ALIGN="CENTER"><TD>abcdefgh</TD><TD>ijklmnop</TD></TR>
</TABLE>
</TD>
</TR>
</TABLE>
</FONT>
<BR>
<P>&nbsp;&nbsp;Which give us, in hexa, <B>009C76:5478</B>. This means that
<B>H5478</B> will be written at <B>H009C76</B> memory offset.</P>
</BODY>
</HTML>

View File

@ -1,715 +0,0 @@
Sega Genesis hardware notes
Version 0.8 (03/02/01)
by Charles MacDonald
WWW: http://cgfm2.emuviews.com
Unpublished work Copyright 2000, 2001 Charles MacDonald
Here is a compilation of some notes I've written up on the Sega Genesis
hardware. Everything described herein has been checked on the real thing,
though that doesn't necessarily mean my testing methods were flawless. :)
Version history
---------------
[0.8]
- Added information on the SVP chip used in Virtua Racing. (section 4.2)
- Added information on EEPROM storage. (section 4.1)
- Changed miscellaneous section around.
[0.7]
- Added more information about access to the Z80 bus. (section 2.2)
- Updated the VDP register information, and removed some things
that were specific to VDP programming. (section 1.1)
- Added some background about the PSG. (section 4)
[0.6]
- Rewrote the 68000 memory map description. (section 1)
- Rewrote the Z80 memory map description. (section 2.1)
- Added memory access section. (section 1.2)
- Added a few miscellaneous topics. (section 4)
[0.5]
- Added more Z80 banking information.
- Added unused VDP address return values from the Z80 side.
- Added example of how to start up the Z80 on power-up.
- Added information on Phantasy Star 4 from Jeff Quinn.
- Added list of consoles that support Mark-III compatibility mode.
- Fixed a few typos.
[0.4]
- Added more details on 68000 and Z80 memory map.
- Added more information on VDP addresses.
- Added some thoughts on Phantasy Star 4.
[0.3]
- Added more information on I/O registers. (section 3)
- Fixed a few typos pointed out by Tim Meekins.
[0.2]
- Added section on I/O port programming and gamepads
[0.1]
- Initial release
Table of Contents
1.) 68000 memory map
1.1) VDP registers
1.2) Memory access quirks
1.3) Clock speeds
2.) Sound hardware overview
2.1) Z80 memory map
2.2) RESET and BUSREQ registers
2.3) Banking
2.4) Interrupts
3.) Input and Output
3.1) Programming I/O ports
3.2) Gamepad specifics
4.) Miscellaneous
4.1) EEPROM
4.2) Virtua Racing
4.3) Phantasy Star 4
4.4) Other topics
5.) Credits
6.) Disclaimer
1.) 68000 memory map
000000-3FFFFFh : ROM
400000-7FFFFFh : Unused (1)
800000-9FFFFFh : Unused (2)
A00000-A0FFFFh : Z80 address space (3)
A10000-A1001Fh : I/O
A10020-BFFFFFh : Internal registers and expansion (4)
C00000-DFFFFFh : VDP (5)
E00000-FFFFFFh : RAM (6)
1. Reads return the MSB of the next instruction to be fetched, with the
LSB set to zero. Writes do nothing.
2. Reading or writing any address will lock up the machine.
This area is used for the 32X adapter.
3. Addresses A08000-A0FFFFh mirror A00000-A07FFFh, so the 68000 cannot
access it's own banked memory. All addresses are valid except for
the VDP which is at A07F00-A07FFFh and A0FF00-A0FFFFh, writing or
reading those addresses will lock up the machine.
4. Reading some addresses lock up the machine, others return the MSB
of the next instruction to be fetched with the LSB is set to zero.
The latter applies when reading A11100h (except for bit 0 reflects
the state of the bus request) and A11200h.
Valid addresses in this area change depending on the peripherals
and cartridges being used; the 32X, Sega CD, and games like Super
Street Fighter II and Phantasy Star 4 use addresses within this range.
5. The VDP is mirrored at certain locations from C00000h to DFFFFFh. In
order to explain what addresses are valid, here is a layout of each
address bit:
MSB LSB
110n n000 nnnn nnnn 000m mmmm
'1' - This bit must be 1.
'0' - This bit must be 0.
'n' - This bit can have any value.
'm' - VDP addresses (00-1Fh)
For example, you could read the status port at D8FF04h or C0A508h,
but not D00084h or CF00008h. Accessing invalid addresses will
lock up the machine.
6. The RAM is 64K in size and is repeatedly mirrored throughout the entire
range it appears in. Most games only access it at FF0000-FFFFFFh.
1.1) VDP registers
The lower five bits of the address specify what memory mapped VDP register
to access:
00h : Data port
02h : Data port
04h : Control port (1)
06h : Control port
08h : HV counter (2)
0Ah : HV counter
0Ch : HV counter
0Eh : HV counter
11h : SN76489 PSG (3)
13h : SN76489 PSG
15h : SN76489 PSG
17h : SN76489 PSG
18h : Unused (4)
1Ah : Unused
1Ch : Unused
1Eh : Unused
1. For reads, the upper six bits of the status flags are set to the
value of the next instruction to be fetched. Bit 6 is always zero.
For example:
move.w $C00004, d0 ; Next word is $4E71
nop ; d0 = -1-- 11?? ?0?? ????
When reading the status flags through the Z80's banked memory area,
the upper six bits are set to one.
2. Writing to the HV counter will cause the machine to lock up.
3. Reading the PSG addresses will cause the machine to lock up.
Doing byte-wide writes to even PSG addresses has no effect.
If you want to write to the PSG via word-wide writes, the data
must be in the LSB. For instance:
move.b (a4)+, d0 ; PSG data in LSB
move.w d0, $C00010 ; Write to PSG
4. Reading the unused addresses returns the next instruction to be fetched.
For example:
move.w $C00018, d0 ; Next word is $4E71
nop ; d0 = $4E71
When reading these addresses through the Z80's banked memory area,
the value returned is always FFh.
Writing to C00018h and C0001Ah has no effect.
Writing to C0001Ch and C0001Eh seem to corrupt the internal state
of the VDP. Here's what each bit does: (assuming word-wide writes)
8E9Fh : These bits cause brief flicker in the current 8 pixels
being drawn when the write occurs.
5040h : These bits blank the display like bit 6 of register #1 when set.
2000h : This bit makes every line show the same random garbage data.
0100h : This bit makes random pattern data appear in the upper eight
and lower ten lines of the display, with the normal 224 lines
in the middle untouched. For those of you interested, the
display is built up like so:
224 lines for the active display
10 lines unused (can show pattern data here with above bit)
3 lines vertical blank (no border color shown)
3 lines vertical retrace (no picture shown at all)
13 lines vertical blank (no border color shown)
8 lines unused (can show pattern data here with above bit)
I know that comes up to 261 lines and not 262. But that's
all my monitor shows.
Turning the display off makes the screen roll vertically,
and random pattern data is displayed in all lines when
this bit is set.
0020h : This bit causes the name table and pattern data shown to
become corrupt. Not sure if the VRAM is bad or the VDP is
just showing the wrong data.
1.2) Memory access quirks
Byte-wide writes
Writing to the VDP control or data ports is interpreted as a 16-bit
write, with the LSB duplicated in the MSB. This is regardless of writing
to an even or odd address:
move.w #$A5, $C00003 ; Same as 'move.w #$A5A5, $C00002'
move.w #$87, $C00004 ; Same as 'move.w #$8787, $C00004'
Byte-wide reads
Reading from even VDP addresses returns the MSB of the 16-bit data,
and reading from odd address returns the LSB:
move.b $C00008, d0 ; D0 = V counter
move.b $C00001, d0 ; D0 = LSB of current VDP data word
move.b $C0001F, d0 ; D0 = $71
nop
move.b $C00004, d0 ; D0 = MSB of status flags
Word-wide writes
When doing word-wide writes to Z80 RAM, only the MSB is written, and
the LSB is ignored:
0000: AA BB CC DD ; Z80 memory
move.w #$1234, $A00000 ; do a word-wide write
0000: 12 BB CC DD ; result
Word-wide reads
A word-wide read from Z80 RAM has the LSB of the data duplicated in the MSB.
0000: AA BB CC DD ; Z80 memory
move.w $A00000, d0 ; do a word-wide read
d0 = $AAAA ; result
1.3) Clock speeds
These are for an NTSC Sega Genesis console.
680000 = 7.67 MHz
YM2612 = 7.67 MHz
Z80 = 3.58 MHz
SN76489 = 3.58 MHz
If anyone has information about timing for PAL consoles, please let me know.
2) Sound hardware overview
The following components used for sound generation:
- Zilog Z80 CPU
- 8k static RAM
- Yamaha YM2612 FM sound generator
- SN76489 PSG
2.1) Z80 memory map
0000-1FFFh : RAM
2000-3FFFh : RAM (mirror)
4000-5FFFh : YM2612 (1)
6000-60FFh : Bank address register (2)
6100-7EFFh : Unused (3)
7F00-7FFFh : VDP (4)
8000-FFFFh : Bank area
1. The YM2612 has two address lines, so it is available at 4000-4003h and
is mirrored repeatedly up to 5FFFh.
2. Writes go to the bank address register, reads return FFh.
The value returned applies to both the 68000 and Z80.
3. Writes are ignored, reads return FFh.
The value returned applies to both the 68000 and Z80.
4. Only addresses 7F00-7F1Fh are valid, writes to 7F20-7FFFh will
lock up the machine.
Z80 access to the VDP has the same results as doing byte-wide reads
and writes as described in section 1.2. So only the HV counter and
PSG can be used effectively.
All I/O ports return FFh, and writing to them has no effect. The Thunder
Force games read port BFh in the IRQ subroutine, this would appear to be
a misunderstanding on the programmer's behalf.
The 68000 can write to A06000h to set up the bank address.
2.2) RESET and BUSREQ registers
Bit 0 of A11100h (byte access) or bit 8 of A11100h (word access) controls
the Z80's /BUSREQ line.
Writing 1 to this bit will request the Z80 bus. You can then release
the bus later on by writing 0.
Reading this bit will return 0 if the bus can be accessed by the 68000,
or 1 if the Z80 is still busy.
If the Z80 is reset, or if it is running (meaning the 68000 does not
have the bus) it will also return 1. The only time it will switch from
1 to 0 is right after the bus is requested, and if the Z80 is still
busy accessing memory or not.
Bit 0 of A11200h (byte access) or bit 8 of A11200h (word access) controls
the Z80's /RESET line.
Writing 0 to this bit will start the reset process. The Z80 manual says you
have to assert the /RESET line for three Z80 clock cycles as a reset does
not happen instantly.
Writing 1 to this bit will stop the reset process. At this point, the Z80
will start executing from address 0000h onwards.
The /RESET line is shared with the YM2612. For as long as the Z80 is reset,
the YM2612 cannot be used.
The Z80 bus can only be accessed by the 68000 when the Z80 is running
and the 68000 has the bus. (as opposed to the Z80 being reset, and/or
having the bus itself)
Otherwise, reading $A00000-A0FFFF will return the MSB of the next
instruction to be fetched, and the LSB will be set to zero. Writes
are ignored. This even applies to the VDP area that would normally
lock up the machine.
Interestingly enough, you can still access $A10000-A1001F during this
time, which seems to be contradictory to some documentation which says
you can only access the I/O region when the 68000 has the bus.
On power-up, the Z80 will be reset and will have the bus.
If you want to load a Z80 program and run it, do the following:
- Stop the reset process
- Request bus
- Load Z80 program
- Start the reset process
- Release bus
- Stop the reset process
2.3) Banking
The Z80 can access the 68000's address space through a banking mechanism
which maps 32k pages to 8000-FFFFh on the Z80 side.
Most games do this to get at large data chunks like YM2612 DAC samples.
However, you can access anything else the 68000 can. (I've tried reading
the version register and setting the VDP border color this way with
success - in fact some 32X sample code shows the PWM sound generator
programmed by the Z80 through banking)
To specify which 32k section you want to access, write the upper nine
bits of the complete 24-bit address into bit 0 of the bank address
register, which is at 6000h (Z80) or A06000h (68000), starting with
bit 15 and ending with bit 23.
For example:
ld ix, $6000 ;
xor a ;
ld (ix), a ; Bit 15 = 0
ld (ix), a ; Bit 16 = 0
ld (ix), a ; Bit 17 = 0
ld (ix), a ; Bit 18 = 0
ld (ix), a ; Bit 19 = 0
ld (ix), a ; Bit 20 = 0
ld (ix), a ; Bit 21 = 0
inc a ;
ld (ix), a ; Bit 22 = 1
ld (ix), a ; Bit 23 = 1
After this routine executes, Z80 addresses 8000-FFFFh now correspond
to 68000 addresses C00000-C07FFFh.
In my own tests, I've been unable to do the following:
- Read banked 68000 RAM. (returns FFh)
- Find result of partial writes to the bank address register.
- Have the Z80 read A00000-A0FFFF through the banked memory area.
(locks up the machine)
Steve Snake informed me that reading 68000 RAM is possible, but is not
a recommended practice by Sega. Perhaps only some models of the Genesis
allow for it.
2.4) Interrupts
The Z80 runs in interrupt mode 1, where an interrupt causes a RST 38h.
However, interrupt mode 0 can be used as well, since FFh will be read
off the bus.
The Z80 will recieve an IRQ from the VDP on scanline E0h. This happens
once per frame, every frame, regardless of frame interrupts being
disabled by the 68000.
If the Z80 has interrupts disabled when the frame interrupt is supposed
to occur, it will be missed, rather than made pending.
There is no way to trigger an NMI unless the Genesis has been switched
into Mark 3 compatability mode, and this only means the NMI line is
mapped to the cartridge port, it's not controllable through software.
3.0) Input and Output
The Genesis has three general purpose I/O ports. Devices like gamepads,
modems, light guns, etc. can be used with them.
Here's a read-out of the I/O registers in their default state. Each
one can be read at an even address (e.g. A1000Dh == A1000Ch) as well.
A10001h = A0 Version register
A10003h = 7F Data register for port A
A10005h = 7F Data register for port B
A10007h = 7F Data register for port C
A10009h = 00 Ctrl register for port A
A1000Bh = 00 Ctrl register for port B
A1000Dh = 00 Ctrl register for port C
A1000Fh = FF TxData register for port A
A10011h = 00 RxData register for port A
A10013h = 00 S-Ctrl register for port A
A10015h = FF TxData register for port B
A10017h = 00 RxData register for port B
A10019h = 00 S-Ctrl register for port B
A1001Bh = FF TxData register for port C
A1001Dh = 00 RxData register for port C
A1001Fh = 00 S-Ctrl register for port C
Bit 7 of the Data registers can be read or written.
Any bit that is set as an input will return '1'.
Any bit that is set as an output will return the value last written.
Bits 7-0 of the Ctrl registers can be read or written.
Bits 7-0 of the TxData registers can be read or written.
The RxData register will always return zero.
Bits 7-4 of the S-Ctrl registers can be read or written.
3.1) Programming I/O ports
In the context of this description, I'll assume the device plugged in is a
gamepad. However, other periperhals like multi-taps, modems, mice, light
guns, etc, exist.
Here's a pin-out of the connector:
Pin 1 - UP
Pin 2 - DOWN
Pin 3 - LEFT
Pin 4 - RIGHT
Pin 5 - Vcc
Pin 6 - TL
Pin 7 - TH
Pin 8 - GND
Pin 9 - TR
Each I/O port has several associated registers. I'll only cover the
data and control registers, as the others are used for serial and
parallel communication.
The data register corresponds to the I/O port pins like so:
Bit 7 - (Not connected)
Bit 6 - TH
Bit 5 - TL
Bit 4 - TR
Bit 3 - RIGHT
Bit 2 - LEFT
Bit 1 - DOWN
Bit 0 - UP
A '0' means a button has been pressed, and '1' means a button has been
released.
Bit 7 isn't connected to any pin on the I/O port. It will latch a value
written to it, as shown:
move.b $A10003, d0 ; D0 = $7F
move.b #$80, $A10003 ; Bit 7 = 1
move.b $A10003, d0 ; D0 = $FF
move.b #$00, $A10003 ; Bit 7 = 0
move.b $A10003, d0 ; D0 = $7F
Bits 6-0 of the control register define what bits of the data register
are inputs or outputs. Gamepads use TH as an output and the remaining
pins as input, so a value of $40 would be written to the control register.
3.2) Gamepad specifics
A gamepad maps the directional pad to the pins mentioned earlier
(left, right, up, down), and multiplexes the four buttons (A, B, C, Start)
through the TL and TR pins.
The TH pin controls which pairs of buttons (either A, Start or C, B) are
output through TL and TR by the multiplexer chip.
In order to read all the buttons, A program will set TH = 1, read the data
port, set TH = 0, and read the port again. The data returned is as follows:
TH = 0 : ?0SA00DU
TH = 1 : ?1CBRLDU
? = Whatever was last written to bit 7.
S = Start
A = Button A
B = Button B
C = Button C
U = Up
D = Down
L = Left
R = Right
A 6-button gamepad allows the extra buttons to be read based on how
many times TH is switched from 1 to 0 (and not 0 to 1). Observe the
following sequence:
TH = 1 : ?1CBRLDU 3-button pad return value
TH = 0 : ?0SA00DU 3-button pad return value
TH = 1 : ?1CBRLDU 3-button pad return value
TH = 0 : ?0SA0000 D3-0 are forced to '0'
TH = 1 : ?1CBMXYZ Extra buttons returned in D3-0
TH = 0 : ?0SA1111 D3-0 are forced to '1'
M = Mode
X = Button X
Y = Button Y
Z = Button Z
From this point on, the standard 3-button pad values will be returned
if any further TH transitions are done.
If TH isn't modified in about 8192 (probably less than that) 68000 CPU
cycles, a 'time-out' will occur and the sequence to read 6-button values
can be done again. Games usually poll the gamepad once per frame,
which is always enough for the time-out to occur.
I believe checking if D3-D0 are all set or clear (as shown in the list
above) would be another method to verify if 6-button or 3-button pad data
was being returned.
Some games may access the gamepad in a way that causes 6-button values
to be returned when 3-button values are expected. To get around this,
the MODE button can be held down when powering-up the console, and
the 6-button gamepad will respond like a 3-button one.
4.) Miscellaneous
The following are miscellaneous topics.
4.1) EEPROM
Some cartridges use a Xicor X24C01 EEPROM chip. The chip is programmed
in a serial fashion (it has only two wires), and has 128 8-bit bytes
of storage.
Games using EEPROM have the backup data string at offset $1B0 in the
cartridge header area formatted like so:
0001B0: 52 41 E8 40 00 20 00 01 00 20 00 01
The Sega manual describes how the above data should be interpreted.
In this case, it corresponds to a device mapped to odd memory addresses,
occupying the byte at $200001.
The only games I know of which use an EEPROM chip are:
- Wonderboy 3 / Monster World IV
- Rockman Megaworld
- Megaman: The Wily Wars
4.2) Virtua Racing
The Virtua Racing cartridge has 2MB ROM, 128K RAM, and a custom DSP chip
called the 'Sega Virtua Processor' (SVP), which is manufactured by Sega.
To the best of my knowledge, the SVP chip has internal ROM and possibly
internal RAM.
The main purpose of the SVP is to render polygons as 8x8 patterns, which
the game program transfers to VRAM from the 128K RAM area using DMA.
The VR cartridge has the following memory map:
000000-1FFFFFh : Program ROM (2MB)
200000-2FFFFFh : Unused
300000-31FFFFh : On-cart RAM (128K)
320000-3FFFFFh : (?)
390000-39FFFFh : (?)
3A0000-3AFFFFh : (?)
The SVP chip has registers mapped in the I/O space:
A15000.w - Can read and write commands
A15005.b - Reading bit 0 acts like a status flag (SVP busy?)
A15006.w - Unknown ($0000, $0001, $000A written)
A15008.w - Unknown ($0000, $0001, $0000 written)
Commands are two bytes in size, and are read and written to A15000h.
FFFFh - Command reset (?) (done before any access)
'SV' - Command init (?) (written before SVP communication)
'OK' - Command OK (?) (written after 'SV')
'Tx' - Where 'x' equals the following value based on the command
selected in the test menu:
0 - "DSP ROM RD" and
"DSP RAM OVER WRITE"
1 - "DSP DRAM R/W"
2 - "DSP IRAM R/W"
4 - "DSP POINTER"
To emulate the SVP chip, somebody needs to figure out how to dump the
internal ROM (the test menu shows that it has a DSP ROM reading option,
perhaps sending a certain command to the SVP makes it map it's internal
ROM within the $300000-$3FFFFF area) and figure out how the DSP works.
All of the above information came from physically examining a VR cartridge,
and from disassembling the test menu code. (found at $1B000 for those
of you who are interested)
4.3) Phantasy Star 4
Phantasy Star 4 is a 24 megabit game with 16k of battery backed RAM
mapped to $200001-$203FFF. (odd addresses used) It has ROM in the same
area where the RAM is. I've observed that the game will always write
$01 to $A130F1 before accessing the RAM, and then write $00 when
done. It could be that bit 0 of $A130F1 controls ROM/RAM banking at
that location.
Jeff Quinn has tested this and confirmed it to work, and also reported
an area of the game where supporting banked SRAM is important; when
your characters encounter a GEROTLUX below the town of Tyler on Dezolis,
the game will try to access the ROM data that is obscured by SRAM.
4.4) Other topics
- The 68000 RESET instruction has no effect.
- If the VDP is not accessed often enough, it will (appear) to lock up.
I'm not sure what the cause is, but any control port access is enough
to keep it going. Maybe some of the internal VDP memory is composed
of DRAM cells that lose their data after a while. This happens in
the Mark III compatability mode as well as mode 4 and mode 5.
- The status of the YM2612 can be read at any of it's four addresses.
Since only address zero is documented as valid, it could be that the
other addresses may return an incorrect result in some situations.
- The PSG is compatible with the Texas Instruments SN76489. It is actually
on the same physical chip as the VDP, and it's output comes directly
out of the VDP to be mixed with the YM2612. Sega did the same thing
with the System C2 (possibly System 18) and SMS VDPs as well.
Can anyone contribute some information about the Genesis security
and operating system ROM features? I know of a few:
- Games must write the text 'SEGA' to A14000h if the lower four
bits of the version register return 01h.
- Writing 01h to A14101h disables the OS ROM and swaps in the cart ROM.
- The OS ROM checks for 'SEGA' or ' SEGA' at offset 100h in the cart ROM.
Here's a list of consoles that support the Mark III compatability mode.
- Sega Mega Drive
- Sega Mega Drive 2
- Sega Genesis
- Sega Genesis 2
And ones that do not:
- Genesis 3 (Majesco)
If anyone has tested this with the Nomad, CDX, MegaJet, etc., please
let me know.
5.) Credits
I would like to thank the following people for contributing information:
Bart Trzynadlowski, Christian Schiller, Flavio Morsoletto, Jeff Quinn,
Mike Gordon, Naflign, Omar Cornut, Steve Snake, and Tim Meekins.
Contributors to the Sega Programming FAQ.
Gringoz for the Genesis schematics.
6.) Disclaimer
If you use any information from this document, please credit me
(Charles MacDonald) and optionally provide a link to my webpage
(http://cgfm2.emuviews.com/) so interested parties can access it.
The credit text should be present in the accompanying documentation of
whatever project which used the information, or even in the program
itself (e.g. an about box)
Regarding distribution, you cannot put this document on another
website, nor link directly to it.

View File

@ -1,458 +0,0 @@
******************************************************
* Sega Genesis Technical Notes by Bart Trzynadlowski *
* and many others! *
******************************************************
Second Edition: February 7, 2000
- Current
- Made a table of contents
- Added tile information and Scroll layer name table information
- Added info on Genesis security system and "do nots" courtesy of
Flavio. He also found a mistake in the joypad notes.
- Added SMD ROM stuff
First Edition: February 3, 2000
- Initial release
This document is intended to be used as a reference alongside sega2.doc or any
other complete Sega Genesis technical documentation, it is not intended as a
standalone resource for learning about the Sega Genesis game console.
There is also some information here pertaining to specific situations
such as using the Starscream 68000 CPU core in an emulator project.
I wrote this document while working on a Genesis emulator. I felt some
things needed more description than was available. This document is intended
for emulator developers and Genesis programmers.
Feel free to pass this document around freely. If you use any parts of
it that were contributed by people other than me, it would be a good idea to
give them credit.
Any useful feedback is very much appreciated, especially corrections
and new entries. Do not ask about ROMs or anything stupid. trzy@powernet.net
Check my page at: http://www.powernet.net/~trzy as well.
Much thanks to Joe Groff, Steve Snake, nyef, ATani, and Flavio for
the invaluable help.
-- Table of Contents --
0. Control Port Write Modes
1. Auto-Increment
2. VRAM Address Decoding (for Writing)
3. Tiles
4. Scroll Layer Name Tables
5. Scroll Layers and Video Resolution
6. Joypads
7. Crash Course on the Genesis Security System and Common Don'ts
8. Emulating RAM and ROM w/ Starscream
9. SMD ROM Format
-- 0. Control Port Write Modes --
The VDP control port, 0xC00004, has two write modes: "Register Set" (write1)
and "Address Set" (write2). The VDP is able to distinguish between which mode
you want to use by looking at bits 15 and 14 of the word you write to the
control port.
10: Write1 Otherwise: Write2
For write2, bits 15 and 14 are CD1 and CD0 so the concern of conflict arises.
If you look at the possible access modes which are specified by the 6 CD bits
you will not find any that have 10 in CD1 and CD0.
-- 1. Auto-Increment --
The auto-increment value (in register #15) is apparently set to 2 by default.
-- 2. VRAM Address Decoding (for Writing) --
For words and longwords, the VRAM address decoding process is not as
straightforward as some would have you believe. The A0 address bit is not used
in decoding, what this apparently means is that it is treated as 0 (thus
preventing misaligned word writes).
A0 is used to test wether or not the bytes in a word should be swapped
or not. If A0 = 1, they are swapped, if it is 0, then bytes are not swapped.
A0 is also used when adding the auto-increment value to the VRAM address after
some data is written.
C example of emulating this:
if (addr & 1)
data = ByteSwap(data);
*((unsigned short int *) (vram + (addr & 0xfffe))) = data;
addr += auto_inc;
-- 3. Tiles --
The Genesis tile format is quite simple. Each pixel is represented by 4 bits
thus allowing 16 colors per every tile. Tiles are 8x8. The Genesis allows for
up to 64 colors to be displayed: 16 per palette, with 4 palettes. Palettes are
not specified in the tile bitmap, that information is elsewhere and beyond the
scope of this note.
Example of a bitmap for the letter "A". We use the color 0xa for each
of the pixels. Remember, color 0 is _always_ transparent in any
palette:
dc.l $00077000
dc.l $07700770
dc.l $07700770
dc.l $07777770
dc.l $07700770
dc.l $07700770
dc.l $00000000
dc.l $00000000
-- 4. Scroll Layer Name Tables --
Scroll layers (who's addresses and sizes are specified in VDP registers) are
"name tables" where each entry contains an index to a specific 8x8 tile. These
entries are arranged in a linear fashion.
Each entry is a word in size. Here is the format for an entry:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|PRI|PL1|PL0|VFP|HFP|I10|I9 |I8 |I7 |I6 |I5 |I4 |I3 |I2 |I1 |I0 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
PRI Priority (1 = highest, on top; 0 = lowest, on bottom)
PL1-PL0 Palette (0, 1, 2, or 3)
VFP Vertical flipping (1 = true)
HFP Horizontal flipping (1 = true)
I10-I0 Index of 8x8 tile in pattern area (VRAM $0000).
Multiply this by 32 to get offset in VRAM of the tile
bitmap
The information here applies to both Scroll A and Scroll B, please refer to
more complete documentation for information on how to set Scroll layer
addresses and what-not.
-- 5. Scroll Layers and Video Resolution --
The Genesis supports two video modes: 32x28 cell and 40x28 cell (which in
pixels are 256x224 and 320x224.) The video resolution is how many 8x8 tiles
are displayed on-screen. The vertical portion differs with PAL I believe, but
it that is not relevant.
Scroll A and Scroll B can have a number of different sizes which
obviously often cannot be all shown on-screen: 32x32, 32x64, 32x128, 64x32,
64x64, and 128x32. The Sega Programming FAQ says that 128x128 is possible, but
I don't think it is since that would take up 32KB of VRAM which would not
leave room for the other Scroll layer, the Window, or the patterns.
Only a portion of the Scroll layer is visible on the screen. How it is
displayed can be represented by the following diagram:
** Assuming the Scroll size is 64x64 and the screen 40x28, everything is
addressed in cell units (obviously not to scale) **
- = Scroll layer
* = Visible portion
H0 H39 H63
+****************************************--------------------+
V0 |* V0 * |
|* * |
|* * |
|* * |
|* * |
|* V27 * |
|**************************************** |
| |
| |
| |
| |
| |
| |
V63 | |
+------------------------------------------------------------+
Thus you can see that there are tiles beyond the right limit of the visible
screen, and below as well. This method of having the layer larger than can be
displayed is for scrolling. The above is what would occur if one set the
Scroll size to 64x64 and the resolution to 40x28 without scrolling the screen
or anything.
If you are having problems emulating Scroll layers because everything
is shifted over you are probably forgetting to render the invisible parts of
the Scroll or to skip over them and on to the next visible row. I hope that
made sense.
-- 6. Joypads --
** Begin Email **
From: Joe Groff
To: Bart Trzynadlowski
Date: Sat, 15 Jan 2000 23:06:49 -0800 (PST)
Subject: Re: DGen/SDL
> is there any good info anywhere on control pad interfacing?
As far as I can tell, this is how the controller works. There are two one-byte
data sets:
v & 0x40: always set
v & 0x20: C
v & 0x10: B
v & 0x08: right
v & 0x04: left
v & 0x02: down
v & 0x01: up
and:
v & 0x40: always clear
v & 0x20: START
v & 0x10: A
v & 0x08: right
v & 0x04: left
v & 0x02: down
v & 0x01: up
By reading a word from 0xA10002 (for first controller) or 0xA10004 (for
second), the word will have one of the above bitmasks written to both bytes.
If you write a byte to 0xA10003(for 1st) or 0xA10005(for 2nd) with the 0x40
bit set, you'll get the first set, otherwise you'll get the second.
Example:
Player 1 is pressing left and the A and B buttons simultaneously. Player 2
is pressing B, C, and START. As the game, in order to probe controller 1:
- I send byte 0x00 to 0xA10003 (or word 0x0000 to 0xA10002 :)
- I read a word from 0xA10002, which gives me 0x1414. From the lower table,
I see A and left are being pressed.
- I send byte 0x40 to 0xA10003.
- I read another word from 0xA10002. This time I get 0x5454, which from the
upper table means B and left are being pressed.
Similarly, to probe controller 2:
- I send byte 0x00 to 0xA10005.
- I read from 0xA10004, and get 0x2020. So START is being depressed.
of the controller!
- I send byte 0x40 to 0xA10005.
- I read from 0xA10004 again, get 0x7070, so B and C are being pressed.
There's also a lot of odd code to handle 6-button controllers in DGen, but
as it's getting a bit late, I can't quite understand it. Hopefully this is
accurate and clear enough to at least get you started.
** End Email **
** Begin Email **
From: ATani
To: Bart Trzynadlowski
Date: Sat, 15 Jan 2000 23:06:43 -0800
Subject: Re: genesis tech question post
Ok, Well on the genesis the joysticks are read in by the z80 and passed to
the 68000 chip via memory addresses: A10003 & A10005.
If bit 6 of the Stored Controller 1 information is set then you return the
following information when reading Address: A10003 (Byte mode):
Bit: Description:
0 Up
1 Down
2 Left
3 Right
4 B
5 C
If Bit 6 is not set return the following:
Bit: Description:
4 A
5 Start
Address A10005 is the same except values returned are for joystick port 2.
The Stored data are in reference to the byte values written to A10003 and
A10005 (joystick port 1 and joystick port 2)
** End Email **
Flavio points out the information from ATani's email may be somewhat faulty:
"The Z80 has nothing to do with joypad reading. Actually, I believe the Z80
banker thingy will go wacko, should you attempt such a stunt. Gotta test
that."
-- 7. Crash Course on the Genesis Security System and Common Don'ts --
** The following information is courtesy of Flavio **
Crash course in Genesis security:
1) There must be either 'SEGA' or ' SEGA' in ASCII at offset 0x100 (256
decimal.)
2) If the four least significant bits of 0xA10001 are higher than zero, the
poor programmer must write 'SEGA' to 0xA14000.
Example:
MOVE.B $A10001, D0
ANDI.B #$F, D0
BEQ.S NO_VDP_LOCK
MOVE.L #'SEGA', $A14000.
NO_VDP_LOCK:
[Yer code here]
Yes, I know many of you can't read 68K ASM yet, but I don't know how to do
this on Paul Lee's C compiler (or any other for that matter.) :/
A list of common Caveat Gennyptor's follows:
- Be careful not to access forbidden addresses (see SEGA2.DOC), as the Genny
locks up instantly if you dare to touch them.
- Don't read from the VDP data port (C00000) if you have sent a
"VRAM/CRAM/VSRAM write" command (and vice versa.)
- The FM doesn't work if the Z80 is reset (their reset lines are wired
together.)
- Always have the Z80 busreq'ed before reading the joyports.
- Never attempt to read PSG ports.
- DMA transfers should be controlled by code placed at the Genny's work RAM
(0xFF0000-0xFFFFFF.)
- Don't attempt to transfer data to/from the VDP if a DMA is in progress.
- Z80 RAM _must_ be accessed in byte units.
- Don't toggle the joystick's select line more than four times per vertical
refresh, to ensure 6-button joypad compatibility.
- It takes at least 16 68K clock ticks for the joyport readouts to become
really stable, after you have toggled the aforementioned select line.
Flavio has also pointed out one more important thing not to attempt:
CLR, ST, and TAS cannot be used to access the C000xx range. (It's a
derivative of the "don't read with the VDP set to write" commandment.)
-- 8. Emulating RAM and ROM w/ Starscream --
Often times, Genesis games do some odd tricks that can be buggers to emulate.
One of these is jumping backwards (which causes the 24-bit address to wrap
around to 0xFFFFFF) into work RAM to execute code. Since Starscream uses
32-bit data to handle addresses, this sort of maneuver would wrap around to
0xFFFFFFFF (32-bit) which is out of the Genesis address space.
Below is part of a Starscream context for emulating the Genesis work
RAM and ROM. I have also included the code for the handlers (Joe Groff helped
with this -- thanks Joe!) The dummy handlers are for regions of the address
space where accesses are ignored (I have removed all references to VDP and I/O
stuff since it would just clutter the example.) In reality, the data items
rom and ram would be dynamically allocated and would have to be added to these
structures during initialization time. They would be seen here as (unsigned)
NULL or (void *) NULL.
struct STARSCREAM_PROGRAMREGION fetch_instructions[] =
{
{ 0x000000, 0x3fffff, (unsigned) rom },
{ 0xff0000, 0xffffff, (unsigned) ram - 0xff0000 },
{ 0xff000000, 0xff3fffff, (unsigned) ram - 0xff000000 },
{ 0xfff00000, 0xffffffff, (unsigned) ram - 0xfff00000 },
{ -1, -1, NULL }
};
struct STARSCREAM_DATAREGION read_data_byte[] =
{
{ 0x000000, 0x3fffff, NULL, (void *) rom },
{ 0x400000, 0xffffff, StarscreamReadRAMByte, NULL },
{ -1, -1, NULL, NULL }
};
struct STARSCREAM_DATAREGION read_data_word[] =
{
{ 0x000000, 0x3fffff, NULL, (void *) rom },
{ 0x400000, 0xdfffff, StarscreamFakeRead, NULL },
{ 0xe00000, 0xffffff, StarscreamReadRAMWord, NULL },
{ -1, -1, NULL, NULL }
};
struct STARSCREAM_DATAREGION write_data_byte[] =
{
{ 0x000000, 0xdfffff, StarscreamFakeWrite, NULL },
{ 0xe00000, 0xffffff, StarscreamWriteRAMByte, NULL },
{ -1, -1, NULL, NULL }
};
struct STARSCREAM_DATAREGION write_data_word[] =
{
{ 0x000000, 0xdfffff, StarscreamFakeWrite, NULL },
{ 0xe00000, 0xffffff, StarscreamWriteRAMWord, NULL },
{ -1, -1, NULL, NULL }
};
unsigned StarscreamReadRAMByte(unsigned address)
{
return ram[(address ^ 1) & 0xffff];
}
unsigned StarscreamReadRAMWord(unsigned address)
{
return *((unsigned short *) (ram + (address & 0xfffe)));
}
void StarscreamWriteRAMByte(unsigned address, unsigned data)
{
ram[(address ^ 1) & 0xffff] = data;
}
void StarscreamWriteRAMWord(unsigned address, unsigned data)
{
*((unsigned short *) (ram + (address & 0xfffe))) = data;
}
unsigned StarscreamFakeRead(unsigned address)
{
return 0;
}
void StarscreamFakeWrite(unsigned address, unsigned data)
{
}
RAM is at 0xff0000-0xffffff and is mirrored every 64KB at 0xe00000-0xfeffff.
Please see the Starscream documentation for information on how the core works.
At the time of this writing, Neill Corlett's page is at:
http://www4.ncsu.edu/~nscorlet/
-- 9. SMD ROM Format --
The SMD ROM format consists of a 512 byte header and the actual ROM image in
16KB chunks with the odd bytes at the beginning, and the even bytes at the
end.
Header offsets:
0x00: Number of 16KB blocks. This number is often incorrect and it
is wise to calculate it manually: (sizeof(file) - 512) / 16384
0x02: If 0, the ROM is standalone or the last part of a series.
Otherwise it is part of a split ROM set.
0x08: 0xaa
0x09: 0xbb
Note: Most ROMs have 0xaa and 0xbb at 0x08 and 0x09 but a very small percentage
(about 1.28% by my calculations) do not conform to this. Those offsets are
useful for checking wether a ROM is in SMD format but be aware that they are
not always correct.
Decoding a 16KB SMD blocke: (thanks to XnaK and Kuwanger)
1. If the byte offset in the block is less than 8192, copy the byte
from the SMD block to the first unused odd offset in the decode
buffer.
2. Otherwise, put it in the first unused even offset in the decode
buffer.
Example block-decoding C function: (from my own GROM v0.75)
void smd_bin(unsigned char *bin_block, unsigned char *smd_block)
{
int i, o = 1, e = 0;
/* convert 16KB of SMD to BIN */
for (i = 0; i < 8192; i++)
{
bin_block[o] = smd_block[i];
bin_block[e] = smd_block[i + 8192];
o += 2;
e += 2;
}
}
Get GROM at:
http://www.powernet.net/~trzy
http://www.zophar.net
http://eidolon.psp.net
http://www.vintagegaming.com
...or...
If all else fails, email me.

View File

@ -1,312 +0,0 @@
----------------------------------------------
SEGA GENESIS EMULATOR SAVE STATE REFERENCE
Third Edition (February 23, 2002)
Bart Trzynadlowski
----------------------------------------------
---------
About
---------
The aim of this reference is to document the save state and backup RAM formats
of the various Sega Genesis emulators out there. Distribute this document
freely, but please keep it unmodified. If you use any of this information,
give credit to the contributors and me.
The following people contributed directly and/or indirectly:
- Charles MacDonald (supplied most of the Genecyst save state information)
- Jeffrey Quinn (found the SSP and USP in Genecyst states)
- Steve Snake (contributed Genecyst and KGen98 information)
- Langoustator (supplied YM2612 register information and some KGen98 data)
More information on any of the formats, especially the KGen format, would be
appreciated. You can reach me at bart@dynarec.com or visit my web site at
http://www.dynarec.com/~bart.
A "byte" is considered to be 8 bits, a "word" is 16 bits, and a "double word"
is 32 bits.
Change History
--------------
February 12, 2002: Second Edition
- Added some Genecyst and KGen save state information
supplied by Steve Snake
- Corrected some typos
April 11, 2001: First Edition
- Initial public release
------------------------------
Genecyst Save State Format
------------------------------
The Genecyst save state format (GST) is used by various emulators. The files
use the extensions GS0-GS9 depending on the save slot. The information in this
section has been validated against Genecyst v0.32b. I believe Version X.XX is
very similar, if not the same, but I would appreciate confirmation.
Offset Range: Description:
------------- ------------
0x00000-0x00002 Signature: "GST"
0x00006 0xE0, apparently used to validate file integrity
0x00007 0x40, apparently used to validate file integrity
0x00080-0x0009F 68K registers D0-D7
0x000A0-0x000BF 68K registers A0-A7
0x000C8-0x000CB 68K PC
0x000D0-0x000D1 68K SR
0x000D2-0x000D5 68K USP
0x000D6-0x000D9 68K SSP
0x000FA-0x00112 VDP registers (0-23, 1 byte each)
0x00112-0x00191 CRAM
0x00192-0x001E1 VSRAM
0x001E4-0x003E3 YM2612 registers
0x00404-0x00437 Z80 registers: AF, BC, DE, HL, IX, IY, PC, SP, AF',
BC', DE', HL', I (stored as a double word each.) R is
not supported and IM is presumed to be 1
0x00438 Z80 IFF1 (IFF2 is assumed to be the same)
0x00439 Z80 status (0 = stopped, 1 = running), probably has
something to do with BUSREQ
0x0043C-0x0043F Z80 window bank
0x00474-0x002473 Z80 RAM
0x02478-0x12477 68K RAM
0x12478-0x22477 VRAM
Steve Snake sent me word that 0x00434 (byte) is the Z80 I register and
0x00437 (byte) is the Z80 interrupt mode. This conflicts with my data
which says 0x00434 is a double word where I is stored. I'm not sure which
is correct.
All data is in little endian format except for 68K RAM, VSRAM, and VRAM, which
are in big endian format. Areas not mentioned should be kept 0.
Locations 0x00006 and 0x00007 are not completely understood. Genecyst expects
them to be 0xE0 and 0x40, respectively. This has been observed in Genecyst
v0.20, v0.32b, and vX.XX. Many emulators avoid saving these bytes and Genecyst
refuses to load their states.
The USP and SSP are tricky. If the supervisor bit in SR is set, only the USP
is saved at 0x000D2, the SSP at 0x000D6 is set to 0. If the supervisor bit is
cleared, both the USP at 0x000D2 and the SSP at 0x000D6 are saved. A7 is also
the current stack pointer (SSP if supervisor mode, USP if user mode.)
Information on the YM2612 registers was sent to me by Langoustator who says it
is valid for Gens save states and is assumed to be valid for true Genecyst
states as well. None of it has been verified by me, but I'll assume it is
correct:
- 0x001E4-0x00205: Apparently unused
- 0x00206-0x00213: General registers (not channel specific.) There are
only 9 registers at: 0x206, 0x208, 0x209, 0x20A,
0x20B, 0x20C, 0x20E, and 0x20F.
- 0x00214-0x002E3: Channel-specific registers for channels 1-3. They are
stored in 4 byte groups with each group layed out like
this:
First byte = Channel 1
Second byte = Channel 2
Third byte = Channel 3
Fourth byte = Unused (0)
The registers only appear to end at 0x0029B and the
rest of the area (from 0x0029C-0x002E3) is unused.
- 0x002E4-0x00313: Apparently unused
- 0x00314-0x003E3: Channel-specific registers for channels 4-6. They are
stored in 4 byte groups like the channel 1-3 registers.
They end at 0x0039B and the rest of the area (from
0x0039C-0x003E3) is unused.
More information is needed, especially on (but not limited to) the following:
- PSG state
- Internal VDP information (control port status, VDP RAM pointer, etc.)
------------------------------
Genecyst Backup RAM Format
------------------------------
Genecyst saves backup RAM in files with the GSV extension. They simply contain
the backup RAM in little endian format. The files do not always have an even
number of bytes.
Even if backup RAM only appears in the odd or even addresses, Genital saves
the unused bytes (which should be 0.)
Those emulators which keep the 68K address space in little endian format can
support GSV files easily: simply copy the contents of the files unmodified to
the backup RAM area.
A few emulators, including Genital, use the GSV format.
----------
KGen98
----------
There is no official information on KGen's save state format, so I decided to
take it upon myself to try reverse engineering the format. Due to a lack of
time, I have not been able to learn more than is shown here. It might be
enough to load states, but isn't enough to save them.
The below information applies to KGen98 v0.4b, I do not know if it applies to
other versions of KGen and KGen98. Any more information is most welcome.
Offset Range: Description:
------------- ------------
0x00000-0x00002 Signature: "KSS"
0x00003 Must be 0x1, also part of the signature
0x00004-0x00005 ROM checksum, word sized
0x00008-0x00096 Path to ROM (zero terminated), when path is at maximum
length, 0x96 contains the last character of the path
0x00097 Always 0
0x00098-0x02097 Z80 RAM
0x02098-0x12097 68K RAM
0x12098-0x22097 VRAM
0x22098-0x22117 CRAM
0x22298-0x222E7 VSRAM
0x2235C-0x2237B 68K registers D0-D7
0x2237C-0x2239B 68K registers A0-A7
0x2239C-0x2239F 68K SP (if supervisor mode: USP, if user mode: SSP)
0x223A0-0x223A3 68K PC
0x223A4-0x223A7 68K SR
0x223A8-0x223AB Previous SR value (Steve says only the high byte is
necessary), used to detect changes between privilege
levels
0x223AE-0x223C5 VDP registers (0-23, 1 byte each)
0x2273E-0x227?? Data written to VDP control port
0x22742-0x22743 Control port half: if only one word of a 2-word
command was written, it is stored here
0x22748-0x22749 Current VDP RAM address
The checksum, 68K RAM, VRAM, CRAM, and VSRAM are stored in big endian format.
Everything else is in little endian format.
I believe location 0x2273E is a little endian double word. There is plenty of
important internal VDP and FM data kept at the end of the file. I haven't
found the meaning of all of it. Also, the path to the save state's ROM file is
saved near the beginning of the file.
-----------------
Genital v1.2+
-----------------
Starting with Version 1.2, Genital save state files use a version numbering
system independent from Genital itself. Save states with different major
version numbers are not compatible. The minor version number indicates changes
in the format which do not affect backwards compatibility.
Version 1.0 of this new GNS format is described below:
Offset Range: Description:
------------- ------------
0x00000-0x00002 Signature: "GNS"
0x00003 Format major version
0x00004 Format minor version
0x00005-0x00007 Reserved (always keep 0)
0x00008-0x00057 68K registers and status (from Genital68K context)
0x00058-0x00077 68K pending interrupts (from Genital68K context)
0x00078-0x10077 68K RAM
0x10078-0x20077 VRAM
0x20078-0x200F7 CRAM
0x200F8-0x20147 VSRAM
0x20148-0x201A7 VDP registers (0-23; double word each)
0x201A8-0x201BF VDP internal status data (taken directly from VDP
context: ctrlport_mode, access_mode, addr, addr_top,
dma_mode, and status_register; double word each)
0x201C0-0x201C3 VDP horizontal interrupt timer
0x201C4-0x201C7 Reserved (always keep 0)
0x201C8-0x201CB Z80 BUSREQ
0x201CC-0x201EB Z80 registers (word each: AF, BC, DE, HL, IX, IY, PC, SP,
AF', BC', DE', HL', IR, IM, IFF1, IFF2)
0x201EC-0x221EB Z80 RAM
Everything is stored in little endian format.
The 68K registers and status come directly from the Genital68K context, occupy
a double word each, and are ordered:
D0-D7, A0-A7, SP, SR, PC, status
The "SP" relies on the privilege mode. If in supervisor mode, this is the USP
(and the SSP is in A7.) If in user mode, this is the SSP (and the USP is in
A7.) Please read the Genital68K (now Turbo68K) documentation for information
on what the "status" is (http://www.dynarec.com/~bart/turbo68k.)
The first 7 elements pending interrupt array correspond to interrupt levels
1-7. Each element, a double word in size, contains the vector of the interrupt
that is pending. The eighth element is the number of interrupts pending.
Again, see the Genital68K documentation for more information.
The VDP internal status comes directly from Genital's VDP context. The
"ctrlport_mode" indicates which part of a command the control port expects. If
0, it expects the first part, otherwise the second. The access_mode is just
the VDP's CD bits which indicate VRAM write, CRAM write, VSRAM write, VRAM
read, etc. The VDP RAM current address is stored in the "addr" element. Bits
15 and 14 of the VDP RAM address are stored in bits 1 and 0 of "addr_top."
These are used to emulate a peculiar feature of the VDP. The "dma_mode" stores
the DMA mode bits. The "status_register" is the VDP Status Register.
The "horizontal interrupt timer" is the count-down timer which triggers
horizontal interrupts.
---------------------------
Genital (v1.0 and v1.1)
---------------------------
The Genital save state format (GNS) was introduced in Genital v1.0 and was
completely changed by v1.2. Versions 1.0 and 1.1 used the format described
below.
Offset Range: Description:
------------- ------------
0x00000-0x0FFFF 68K RAM
0x10000-0x1FFFF VDP VRAM
0x20000-0x21FFF Z80 RAM
0x22000-0x2207F VDP CRAM
0x22080-0x220CF VDP VSRAM
0x220D0-0x220EF 68K registers A0-A7
0x220F0-0x220F3 68K SP (if supervisor mode: USP, if user: SSP)
0x220F4-0x22113 68K registers D0-D7
0x22114-0x22117 68K SR
0x22118-0x2211B 68K PC
0x2211C-0x2214F Z80 registers: AF, BC, DE, HL, IX, IY, PC, SP, AF',
BC', DE', HL', IR (stored as a double word each)
0x22150-0x22153 Z80 BUSREQ
0x22154-0x221B3 VDP registers (0-23, double word each)
0x221B4-0x221B7 VDP control port mode
0x221B8-0x221BB VDP RAM address pointer
0x221BC-0x221BF VDP RAM access mode
0x221C0-0x221C3 VDP DMA mode
0x221C4-0x221C7 VDP Status Register
0x221C8-0x221CB VDP HV counter
0x221CC-0x221CF VDP Horizontal Interrupt timer
0x221D0-0x221D3 VDP Control Port A15, A14
0x221D4-0x221DA Reserved (7 bytes; should be 0)
0x221DB Major version number of Genital
0x221DC Minor version number of Genital
0x221DD-0x221DF Signature: "GNS"
The 68K RAM, VRAM, CRAM, and VSRAM are stored in big endian format. Everything
else is in little endian format.
The VDP RAM address pointer is the current VRAM, CRAM, or VSRAM address. The
VDP RAM access mode is just the CD bits in a VDP command which indicate
whether the VDP is in VRAM write mode, VRAM read mode, CRAM write mode, etc.
The VDP Control Port mode indicates which part of the command the VDP is
expecting. This is the "pending flag" described by Charles MacDonald's VDP
document. The A15, A14 bits are those last written to the control port. When
the first word of an address set command is written, these bits are used to
fill in A15, A14. They are stored in bits 1 and 0 of the GNS double word.
The major and minor version numbers reflect the version of Genital which
produced the save state. For example, if the state was created with Genital
v1.0, the major version would be 1 and the minor would be 0. The signature
must be "GNS" in ASCII or the save state will be deemed corrupt.

File diff suppressed because it is too large Load Diff

View File

@ -1,933 +0,0 @@
<html><head><title>Sega Genesis I/O Chip and Peripherals</title></head><body>
<h2>Sega Genesis I/O Chip and Peripherals</h2>
By Charles MacDonald<br>
<a href="http://cgfm2.emuviews.com/">http://cgfm2.emuviews.com</a>
<hr>
<h4>Contents</h4>
<ul>
<li><a href="#ovr">Overview</a>
</li><li><a href="#con">Connector details</a>
</li><li><a href="#cpu">CPU interface</a>
</li><li><a href="#reg">Register list</a>
</li><li><a href="#ver">Version register</a>
</li><li><a href="#dat">Data register</a>
</li><li><a href="#dir">Control register</a>
</li><li><a href="#scr">Serial control register</a>
</li><li><a href="#txd">TxData register</a>
</li><li><a href="#rxd">RxData register</a>
</li><li><a href="#ser">Using serial communication</a>
</li><li><a href="#per">Peripheral devices</a>
<ul>
<li><a href="#md2">2-button Mark-III gamepad</a>
</li><li><a href="#md3">3-button standard gamepad</a>
</li><li><a href="#md6">Fighting Pad 6B</a><i>(incomplete)</i>
</li><li><a href="#gun">Lightguns (Sega Menacer, Konami Justifier)</a><i>(incomplete)</i>
</li><li><a href="#eat">EA 4-Way Play</a>
</li><li><a href="#mul">Sega Team Player</a><i>(incomplete)</i>
</li><li><a href="#mmo">Sega Mega Mouse</a>
</li></ul>
</li><li><a href="#msc">Miscellaneous</a>
</li><li><a href="#dis">Disclaimer</a>
</li></ul>
<a name="ovr">
</a><h4><a name="ovr">Overview</a></h4>
<p>
<a name="ovr"> The I/O chip manages three 7-bit I/O ports. It also
provides an way for the CPU to read the state of several jumpers in the
system. Later versions of the Genesis hardware have the I/O chip
integrated into some of the other custom hardware, but they all
function identically.
</a></p>
<a name="con">
</a><h4><a name="con">Connector details</a></h4>
<p>
<a name="con"> Ports A and B are male DB-9 connectors, while port C is
female. In the Genesis 2 and 3, there is no physical connector for port
C, but it can still be programmed and will respond like any other port.
(as if no gamepad was connected) Here are the pin assignments:
</a></p>
<pre><a name="con"> Pin 1 : D0
Pin 2 : D1
Pin 3 : D2
Pin 4 : D3
Pin 5 : +5V
Pin 6 : TL
Pin 7 : TH
Pin 8 : Ground
Pin 9 : TR
</a></pre>
<a name="cpu">
</a><h4><a name="cpu">CPU interface</a></h4>
<p>
<a name="cpu"> The I/O chip is connected to the 68000 and Z80. When in
Mark-III compatibility mode, the I/O chip has a different set of
registers which mimic those of the SMS, which will not be discussed
here.
<br><br>
The I/O chip is mapped to $A10000-$A1001F in the 68000/VDP/Z80 banked address space.
It is normally read and written in byte units at odd addresses.
The chip gets /LWR only, so writing to even addresses has no effect.
Reading even addresses returns the same data you'd get from an odd address.
If a word-sized write is done, the LSB is sent to the I/O chip and the MSB is ignored.
Here are some examples to illustrate these points:
</a></p><pre><a name="cpu"> ; Does nothing, byte writes to even addresses are ignored
move.b #$40, $A10002
; Returns contents of version register, reading even addresses is the same as reading odd ones
move.b $A10000, d0
; Same as writing #$40 to $A10007, the MSB is ignored
move.w #$C040, $A10006
</a></pre>
<p></p>
<a name="reg">
</a><h4><a name="reg">Register list</a></h4>
<table bgcolor="#f0f0f0" border="0" cellpadding="4">
<tbody><tr bgcolor="#cccccc">
<td>Address</td>
<td>Description</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10001</td>
<td>Version</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10003</td>
<td>Port A data</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10005</td>
<td>Port B data</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10007</td>
<td>Port C data</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10009</td>
<td>Port A control</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A1000B</td>
<td>Port B control</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A1000D</td>
<td>Port C control</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A1000F</td>
<td>Port A TxData</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10011</td>
<td>Port A RxData</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10013</td>
<td>Port A serial control</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10015</td>
<td>Port B TxData</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10017</td>
<td>Port B RxData</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10019</td>
<td>Port B serial control</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A1001B</td>
<td>Port C TxData</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A1001D</td>
<td>Port C RxData</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A1001F</td>
<td>Port C serial control</td>
</tr>
</tbody></table>
<a name="ver">
</a><h4><a name="ver">Version register</a></h4>
<p>
<a name="ver"> The version register returns several types of
information, such as a hard-coded version number, settings of the
domestic/export and PAL/NTSC jumpers, and the state of a sense pin
which the Sega CD uses. </a></p><pre><a name="ver"> D7 : Console is 1= Export (USA, Europe, etc.) 0= Domestic (Japan)
D6 : Video type is 1= PAL, 0= NTSC
D5 : Sega CD unit is 1= not present, 0= connected.
D4 : Unused (always returns zero)
D3 : Bit 3 of version number
D2 : Bit 2 of version number
D1 : Bit 1 of version number
D0 : Bit 0 of version number
</a></pre>
<a name="ver"> Bit 5 is used by the Sega CD, returning '0' when it is attached and '1' when it is not.
<br><br>
The version number is zero for the original model Genesis and MegaDrive.
All later versions of the hardware are version 1, and have additional security hardware.
<br><br>
Bits 7,6 are used in country protection checks. Some early games used
them to display English or Japanese text, so the same game program could
be used in both regions. Here's a list of settings:
</a><p></p>
<table bgcolor="#f0f0f0" border="0" cellpadding="4">
<tbody><tr bgcolor="#cccccc">
<td>Bit 7</td>
<td>Bit 6</td>
<td>TV type</td>
<td>Region</td>
<td>Comments</td>
</tr>
<tr bgcolor="#dddddd">
<td>0</td>
<td>0</td>
<td>NTSC</td>
<td>Japan, Korea, Taiwan</td>
<td>262 lines, 60 FPS</td>
</tr>
<tr bgcolor="#dddddd">
<td>0</td>
<td>1</td>
<td>PAL</td>
<td>Japan</td>
<td>No hardware actually uses this setting</td>
</tr>
<tr bgcolor="#dddddd">
<td>1</td>
<td>0</td>
<td>NTSC</td>
<td>USA, Canada</td>
<td>262 lines, 60 FPS</td>
</tr>
<tr bgcolor="#dddddd">
<td>1</td>
<td>0</td>
<td>PAL-M</td>
<td>Brazil</td>
<td>262 lines, 60 FPS</td>
</tr>
<tr bgcolor="#dddddd">
<td>1</td>
<td>1</td>
<td>PAL</td>
<td>Europe, Hong Kong</td>
<td>313 lines, 50 FPS</td>
</tr>
</tbody></table>
<p>
<a name="ver"> Early games stored a region compatibility code in their
header at offset $0001F1. This value could be the ASCII text J, U, or E
for Japan, USA or Europe. During game initialization, bits 7,6 could be
sampled and compared to the region type stored in the header. If there
is a mismatch, many games will fill the screen with a single color lock
up intentionally, or sometimes display an error message. <br><br>
Later games have a slightly more complex code.
Here's the table Sega uses to determine valid codes to use:
</a></p>
<table bgcolor="#f0f0f0" border="0" cellpadding="4">
<tbody><tr bgcolor="#cccccc">
<td colspan="2">$A10001</td>
<td>&nbsp;</td>
<td rowspan="2">Main Sales Territories</td>
<td colspan="16">Hardware Enable Code (numbers from 0 to F below)</td>
</tr>
<tr bgcolor="#cccccc">
<td>Bit 7</td>
<td>Bit 6</td>
<td>Hardware Type</td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>A</td>
<td>B</td>
<td>C</td>
<td>D</td>
<td>E</td>
<td>F</td>
</tr>
<tr bgcolor="#dddddd">
<td>0</td>
<td>0</td>
<td>Japan, NTSC</td>
<td>Japan, S. Korea, Taiwan</td>
<td>X</td>
<td>O</td>
<td>X</td>
<td>O</td>
<td>X</td>
<td>O</td>
<td>X</td>
<td>O</td>
<td>X</td>
<td>O</td>
<td>X</td>
<td>O</td>
<td>X</td>
<td>O</td>
<td>X</td>
<td>O</td>
</tr>
<tr bgcolor="#dddddd">
<td>0</td>
<td>1</td>
<td>Japan, PAL</td>
<td>&nbsp;</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
</tr>
<tr bgcolor="#dddddd">
<td>1</td>
<td>0</td>
<td>Overseas, NTSC</td>
<td>N. America, Brazil</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
</tr>
<tr bgcolor="#dddddd">
<td>1</td>
<td>1</td>
<td>Overseas, PAL</td>
<td>Europe, Hong Kong</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
</tr>
</tbody></table>
<p>
<a name="ver"> Common uses of the new code type are ASCII values '4' for N.America, 'A' for UK, and 'B' for UK and Japan.
</a></p>
<a name="dat">
</a><h4><a name="dat">Data register</a></h4>
<p>
<a name="dat"> Writing to the data register sets the logic level of
pins configured as outputs (0= 0V, 1= +5V), and does nothing to pins
configured as inputs. Reading from the data register returns the state
of each pin. Here's a list of which bits in the data register
correspond to pins on the I/O port.
</a></p><pre><a name="dat"> D7 : Unused. This bit will return any value written to it
D6 : TH pin
D5 : TR pin
D4 : TL pin
D3 : D3 pin
D2 : D2 pin
D1 : D1 pin
D0 : D0 pin
</a></pre>
<a name="dat"> If a pin is configured as an input, reading it returns
the true logic state of whatever the pin is connected to (e.g. 0 for
ground, 1 for +5V). If nothing is connected to it, the pin returns '1',
maybe due to internal pull-up resistors.
<br><br>
If a pin is configured as an output, reading it returns the last value written to this register.
</a><p></p>
<a name="dir">
</a><h4><a name="dir">Control register</a></h4>
<p>
<a name="dir"> The control register determines which pins are inputs and outputs.
</a></p><pre><a name="dir"> D7 : /HL output control (see description)
D6 : TH pin is 1=output, 0=input
D5 : TR pin is 1=output, 0=input
D4 : TL pin is 1=output, 0=input
D3 : D3 pin is 1=output, 0=input
D2 : D2 pin is 1=output, 0=input
D1 : D1 pin is 1=output, 0=input
D0 : D0 pin is 1=output, 0=input
</a></pre>
<a name="dir"> If bit 7 of this register is set, and TH is configured as an input,
then whenever external hardware makes high to low transition on TH
the I/O chip will strobe it's /HL output pin low. This pin connects to
the VDP, which can be set up to latch the HV counter and/or cause a level 2
interrupt upon /HL going low.
</a><p></p>
<a name="scr">
</a><h4><a name="scr">Serial control register</a></h4>
<p>
<a name="scr"> The serial control register defines how a port is used for serial
communications and provides status flags to indicate the current state
of sending or receiving data.
</a></p><pre><a name="scr"> D7 : Serial baud rate bit 1
D6 : Serial baud rate bit 0
D5 : TR pin functions as 1= serial input pin, 0= normal
D4 : TL pin functions as 1= serial output pin, 0= normal
D3 : 1= Make I/O chip strobe /HL low when a byte has been received, 0= Do nothing
D2 : 1= Error receiving current byte, 0= No error
D1 : 1= Rxd buffer is ready to read, 0= Rxd buffer isn't ready
D0 : 1= Txd buffer is full, 0= Can write to Txd buffer
</a></pre>
<a name="scr"> The available baud rates are:
</a><p></p>
<table bgcolor="#f0f0f0" border="0" cellpadding="4">
<tbody><tr bgcolor="#cccccc">
<td>D7</td>
<td>D6</td>
<td>Baud rate</td>
</tr>
<tr bgcolor="#dddddd">
<td>0</td>
<td>0</td>
<td>4800 bps</td>
</tr>
<tr bgcolor="#dddddd">
<td>0</td>
<td>1</td>
<td>2400 bps</td>
</tr>
<tr bgcolor="#dddddd">
<td>1</td>
<td>0</td>
<td>1200 bps</td>
</tr>
<tr bgcolor="#dddddd">
<td>1</td>
<td>1</td>
<td>300 bps</td>
</tr>
</tbody></table>
<p>
<a name="scr"> When doing serial communication, TL and/or TR can be used for sending
and receiving data. During this time the data and control registers
have no effect for whichever pin(s) are in serial mode. The rest of the
pins in the same port function normally.
<br><br> The intended use of bit 3 is to also have the VDP set up to
enable level 2 interrupts when /HL goes low. This way, when the I/O
chip receives a byte through the TR pin, if this bit is set then it
will strobe /HL low and cause an interrupt. So receiving data serially
can either be accomplished through manual polling or be interrupt
driven.
<br><br>
Bits 2-0 are read-only status flags, the rest of the bits in this register can be read and written.
</a></p>
<a name="txd">
</a><h4><a name="txd">TxData register</a></h4>
<p>
<a name="txd"> Writing a byte to this register will make the I/O chip
output the data serially through the TL pin, providing it was
configured for serial mode. You should poll bit 0 of the serial control
register until the bit returns 0 to ensure the previously written byte
has been sent and the TxData buffer is empty.
</a></p>
<a name="rxd">
</a><h4><a name="rxd">RxData register</a></h4>
<p>
<a name="rxd"> Reading from this register returns the last byte
received serially through the TR pin. You should check bits 3,2 of the
serial control register to ensure that the RxData input buffer is full
and that there were no errors in receiving the byte (which would then
be invalid).
</a></p>
<a name="ser">
</a><h4><a name="ser">Using serial communication</a></h4>
<p>
<a name="ser"> When in serial mode, the I/O ports output TTL-level
signals. You need something like a MAX232 line driver to convert these
to RS-232 compatible signals for interfacing with (for example) a PC.
<br><br> If you just want to do experiments on the serial ports
themselves, you can use a null modem cable with the TL/TR wires
switched around to connect port A to B. I used this for testing the
serial capabilities while writing this document. Be sure to disconnect
the +5V line as well.
</a></p>
<a name="per">
</a><h2><a name="per">Peripheral devices</a><hr></h2>
<ul>
<li><a href="#md2">2-button Mark-III gamepad</a>
</li><li><a href="#md3">3-button standard gamepad</a>
</li><li><a href="#md6">Fighting Pad 6B</a>
</li><li><a href="#gun">Lightguns (Sega Menacer, Konami Justifier)</a>
</li><li><a href="#eat">EA 4-Way Play</a>
</li><li><a href="#mul">Sega Team Player</a>
</li><li><a href="#mmo">Sega Mega Mouse</a>
</li></ul>
<a name="md2">
</a><h4><a name="md2">2-button Mark-III gamepad</a></h4>
<p>
<a name="md2"> This controller has a 4-way direction pad, and two buttons (2 and 1).
Here's a description of how the controller interfaces with an I/O port:
</a></p><pre><a name="md2"> D6 : (TH) Not used
D5 : (TR) Button 2
D4 : (TL) Button 1
D3 : (D3) D-pad Right
D2 : (D2) D-pad Left
D1 : (D1) D-pad Down
D0 : (D0) D-pad Up
</a></pre>
<a name="md2"> All buttons are active-low logic, so they return '0' when pressed and '1' when released.
</a><p></p>
<a name="md3">
</a><h4><a name="md3">3-button standard gamepad</a></h4>
<p>
<a name="md3"> This controller has a 4-way direction pad, and four buttons (Start, A, B, C).
It uses a multiplexer that selects 1 of 2 inputs using TH, and routes buttons Start or C to TR, and B or A to TL.
<br><br>
Here's a description of how the controller interfaces with an I/O port:
</a></p><pre><a name="md3"> When TH=0 When TH=1
D6 : (TH) 0 1
D5 : (TR) Start button Button C
D4 : (TL) Button A Button B
D3 : (D3) 0 D-pad Right
D2 : (D2) 0 D-pad Left
D1 : (D1) D-pad Down D-pad Down
D0 : (D0) D-pad Up D-pad Up
</a></pre>
<a name="md3"> All buttons are active-low logic, so they return '0' when pressed and '1' when released.
<br><br> You need a small delay between changing TH and reading the
button state back, as the multiplexer takes some time in switching
inputs. I've found about four NOPs provides a reasonable delay.
<br><br>
Here's some example code to read a 3-button gamepad:
</a><p></p>
<table bgcolor="#e0e0e0" width="70%"><tbody><tr><td><pre>; Returns D0 with the button states: 'SACBRLDU'
_read_joypad:
move.l d1, -(a7)
move.b #$40, $A10003
nop
nop
move.b $A10003, d0
andi.b #$3F, d0
move.b #$00, $A10003
nop
nop
move.b $A10003, d1
lsl.b #2, d1
andi.b #$C0, d1
or.b d1, d0
eori.b #$FF, d0
move.l (a7)+, d1
rts
</pre></td></tr></tbody></table>
<a name="md6">
</a><h4><a name="md6">Fighting Pad 6B</a></h4>
<p>
<a name="md6"> Information coming soon.
</a></p>
<a name="gun">
</a><h4><a name="gun">Lightguns (Sega Menacer, Konami Justifier)</a></h4>
<p>
<a name="gun"> Information coming soon.
</a></p>
<a name="eat">
</a><h4><a name="eat">EA 4-Way Play</a></h4>
<p>
<a name="eat"> The EA 4-Way Play plugs into ports A and B, and allows up to four standard Genesis controllers to be connected at once.
<br><br> I've determined how the multitap works by examining the
joystick reading code from NHL '95 and trying the same routine on a
new-style Sega Team Player in 'EXTRA' mode. That said, the actual EA
4-Way Play could have some differences that Sega's compatibility mode
doesn't take care of.
<br><br> To detect the multitap, set CTRL1 to 0x40, CTRL2 to 0x7F and
DATA2 to $7C. Reading the lower 2 bits of DATA1 will return zero if the
multitap is present. Usually these bits return 0x03 if there is no tap,
no controller, or the Sega Team Player isn't in EXTRA mode, but this
could be a behavior specific to the Team Player.
<br><br>
To read the pads, write 0x0C, 0x1C, 0x2C, or 0x3C to DATA2 to select the controller in port A, B, C, or D.
You can then use DATA1/CTRL1 to read the pad state just like polling a regular 3-button pad in port A.
<br><br>
Here's some example code to use the EA 4-Way Play:
</a></p>
<table bgcolor="#e0e0e0" width="70%"><tbody><tr><td><pre>; Returns D0 == 0 if the multitap is present, or D0 != 0 if it isn't
_detect_4wayplay:
move.b #$40, $A10009
nop
move.b #$7F, $A1000B
nop
move.b #$7C, $A10005
nop
moveq #0, d0
move.b $A10003, d0
andi.b #$03, d0
rts
; Returns the state of all four 3-button gamepads in D0
_read_4wayplay:
move.l d1-d3/a0, -(a7)
lea $A10000, a0
move.l #$0C1C2C3C, d2
moveq #$03, d3
poll: move.b d2, $05(a0)
nop
nop
move.b #$40, $03(a0)
nop
nop
move.b $A10003, d0
andi.b #$3F, d0
move.b #$00, $03(a0)
nop
nop
move.b $03(a0), d1
lsl.b #2, d1
andi.b #$C0, d1
or.b d1, d0
lsl.l #8, d0
lsr.l #8, d2
dbra d3, poll
eori.l #-1, d0
move.l (a7)+, d2-d3/a0
rts
</pre></td></tr></tbody></table>
<a name="mul">
</a><h4><a name="mul">Sega Team Player</a></h4>
<p>
<a name="mul"> The Team Player is a multitap device that allows four peripherals to be connected to the Genesis at one time.
It has a mode select switch with several settings:
</a></p><pre><a name="mul"> EXTRA - All four ports are enabled. This is the setting used by
EA 4-Way Play compatible games.
A - Routes the peripheral in port A to port A of the Genesis.
B - Routes the peripheral in port B to port A of the Genesis.
C - Routes the peripheral in port C to port A of the Genesis.
D - Routes the peripheral in port D to port A of the Genesis.
MULTI - All four ports are enabled. This is the setting used by
Team Player compatible games.
</a></pre>
<a name="mul"> Sega made two versions of the Team Player. The first one
was not compatible with the EA 4-Way Play and only had one cable to
connect it to port A. The second one added the "EXTRA" setting for EA
4-Way Play compatibility and provides a second cable to connect it to
port B as well. Both seem to function identically with the exception of
EXTRA mode.
<br><br>
I don't have any programming information for this device.
</a><p></p>
<a name="mmo">
</a><h4><a name="mmo">Sega Mega Mouse</a></h4>
<p>
<a name="mmo"> This is a three button mouse (left, middle, right) with an extra button
(Start) located near the thumb position. It uses a PIC16C54 microcontroller
which manages the buttons and position tracking.
<br><br>
The Sega Mega Mouse that is distributed in North America is incompatible with the European version of Populous 2.
The mouse functions normally but has Y axis inverted so up is down and vice-versa.
It may have been designed for the Japanese Mega Drive mouse, which is a <b>different</b> product with 2 buttons and unique physical appearance.
<br><br>
The protocol works as follows:
TH and TR are outputs which tell the microcontroller to stop or start a data transfer, and to acknowledge received data.
TL is an input which returns a busy flag for the microcontroller.
D3-D0 are inputs that return the data.
Here's a table showing the communication process:
</a></p>
<table bgcolor="#f0f0f0" border="0" cellpadding="4">
<tbody><tr bgcolor="#cccccc">
<td>Write</td>
<td>TH</td>
<td>TR</td>
<td>TL</td>
<td>D3</td>
<td>D2</td>
<td>D1</td>
<td>D0</td>
<td>Description</td>
</tr>
<tr bgcolor="#dddddd">
<td>$60</td>
<td bgcolor="#bbbbbb">1</td>
<td bgcolor="#bbbbbb">1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>Request data</td>
</tr>
<tr bgcolor="#dddddd">
<td>$20</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>ID #0 ($0)</td>
</tr>
<tr bgcolor="#dddddd">
<td>$00</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>ID #1 ($B)</td>
</tr>
<tr bgcolor="#dddddd">
<td>$20</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>ID #2 ($F)</td>
</tr>
<tr bgcolor="#dddddd">
<td>$00</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>ID #3 ($F)</td>
</tr>
<tr bgcolor="#dddddd">
<td>$20</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">1</td>
<td>0</td>
<td>Y Over</td>
<td>X Over</td>
<td>Y Sign</td>
<td>X Sign</td>
<td>Axis sign and overflow</td>
</tr>
<tr bgcolor="#dddddd">
<td>$00</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">0</td>
<td>1</td>
<td>Start</td>
<td>Middle</td>
<td>Right</td>
<td>Left</td>
<td>Button state</td>
</tr>
<tr bgcolor="#dddddd">
<td>$20</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">1</td>
<td>0</td>
<td>X7</td>
<td>X6</td>
<td>X5</td>
<td>X4</td>
<td>X axis MSN</td>
</tr>
<tr bgcolor="#dddddd">
<td>$00</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">0</td>
<td>1</td>
<td>X3</td>
<td>X2</td>
<td>X1</td>
<td>X0</td>
<td>X axis LSN</td>
</tr>
<tr bgcolor="#dddddd">
<td>$20</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">1</td>
<td>0</td>
<td>Y7</td>
<td>Y6</td>
<td>Y5</td>
<td>Y4</td>
<td>Y axis MSN</td>
</tr>
<tr bgcolor="#dddddd">
<td>$00</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">0</td>
<td>1</td>
<td>Y3</td>
<td>Y2</td>
<td>Y1</td>
<td>Y0</td>
<td>Y axis LSN</td>
</tr>
</tbody></table>
<p>
<a name="mmo"> Write #$60 when you are done polling to stop the data
transfer. If you continue to poll the mouse after collecting all the
data by writing $20 / $00, the Y axis LSN will always be returned. Sega
advises polling beyond this point will make the mouse behave
abnormally. It's possible that the PIC code in some versions of the
Mega Mouse may have problems if the poll sequence is too long.
<br><br>
The X/Y overflow flags are supposed to be set if the mouse is moved over a distance greater than can be measured.
I can't get them to become set, maybe the mouse supports a fairly wide range of movement.
<br><br> You need a considerable delay between writing new values to
TH/TR. I think the intention is to poll TL until the microcontroller
returns 'not busy', but I can't get this to work reliably. Sega's mouse
reading code also has a timeout when checking TL which would indicate
it may get stuck in a certain state.
<br><br>
All buttons (start, left, middle, right) are active-high logic, so they return '1' when pressed and '0' when released.
</a></p>
<a name="msc">
</a><h4><a name="msc">Miscellaneous</a></h4>
<p>
<a name="msc"> After power-up, the default state of the I/O chip are as follows:
</a></p><pre><a name="msc"> $A10001 = $80 (Bits 7,6,5 depend on the domestic/export, PAL/NTSC jumpers and having a Sega CD or not)
$A10003 = $7F
$A10005 = $7F
$A10007 = $7F
$A10009 = $00
$A1000B = $00
$A1000D = $00
$A1000F = $FF
$A10011 = $00
$A10013 = $00
$A10015 = $FF
$A10017 = $00
$A10019 = $00
$A1001B = $FB
$A1001D = $00
$A1001F = $00
</a></pre>
<p></p>
<a name="dis">
</a><h4><a name="dis">Disclaimer</a></h4>
<pre><a name="dis"> If you use any information from this document, please credit me
(Charles MacDonald) and optionally provide a link to my webpage
(http://cgfm2.emuviews.com/) so interested parties can access it.
The credit text should be present in the accompanying documentation of
whatever project which used the information, or even in the program
itself (e.g. an about box)
Regarding distribution, you cannot put this document on another
website, nor link directly to it.
</a></pre>
<hr>
</body></html>

View File

@ -1,40 +0,0 @@
VDP timing for an NTSC Genesis in display mode 5.
Version 0.4 (11/29/00)
by Charles MacDonald
WWW: http://cgfm2.emuviews.com
Unpublished work Copyright 2000 Charles MacDonald
Description 32-cell 40-cell
----------------------------------------------------------------------------
Range 00-93, E9-FF 00-B6, E4-FF
Display area 00-7F 00-9F
V counter increment 84, 85 A4, A5
V-blanking in 86, 87 A7, A8
V-blanking out 86, 87 A7, A8
H-blanking in 93, E9 B2, E4
H-blanking out 06, 07 06, 07
Comma seperated values show the H counter value before an event occurs,
and then the H counter value immediately after.
These values shouldn't be considered 100% accurate, they are probably
off by one or two.
Each H counter unit is equivalent to two pixels.
The gaps at 93-E9 and B6-E4 are where the H counter 'jumps' ahead.
The H counter will never actually be set to the values 94-E8 or B7-E3.
Perhaps this is the horizontal retrace period.
Interestingly enough, the timing values for the 32-cell display mode
are identical to that of the SMS.
It would appear that in 40-cell mode, the horizontal blanking period
is shorter as the active display period takes more time.
The V-blanking flag can also be forcibly set by disabling the display
through bit 6 of register #1.

View File

@ -1,105 +0,0 @@
After some testing, it turns out that the unused VDP address $C0001C
(mirrored at $C0001E) controls how the VDP generates the display.
Specifically, it allows layers to be turned on and off, it affects how
high priority sprites or tiles are interpreted, and it seems to change
how layers are combined together.
No games use this register to my knowledge, maybe it was left in for
testing or debugging purposes by the VDP manufacturer. This was all
checked on an original model Genesis, the register may not be present
or behave differently in later versions of the VDP hardware.
Here's the layout of $C0001C/$C0001E:
MSB LSB
-gfe ---d cba- ----
Notes:
Unmarked bits have no effect.
Anything pertaining to plane A also applies to the window layer.
Any description about color intensity changes is only valid when
the VDP is in shadow/hilight mode.
a = Display garbage (bad pattern data) on all background rows
and for the sprites.
b = Turn display off (background and sprites)
Display is filled with background color.
CRAM data is randomly corrupted as long as this bit is set.
c = Turn display off (background only)
In shadow/hilight mode, high priority tiles are also invisble
but are drawn in the regular normal intensity backdrop color,
while low priority tiles are drawn in the half intensity
backdrop color.
Transparent pixels in high priority sprites are also filled
with the normal intensity backdrop color, so sprites have
a tile shaped outline around them.
It seems like either underlying pixels from the background
are visible through shadow/hilight pixels in sprites, but
the colors are wrong. (as if they were logically OR'd with
the sprite pixels, as both layers can be seen)
CRAM data is randomly corrupted as long as this bit is set.
** When 'c' and 'b' are set, the background layers are invisible,
but sprites are not. All sprites, regardless of priority,
have a tile shaped outline around them that is drawn in some
color other than the backdrop color. (can't exactly tell)
d = When set, garbage is displayed in the top and bottom border areas.
Plane B is disabled, only plane A is visible.
All sprites are drawn in the regular intensity backdrop color.
High priority plane B tiles are drawn in the regular intensity
background color, low priority plane B tiles are drawn in the
half intensity backdrop color.
g,f,e = All bits turn off sprites when set.
If bit 'd' is set, bit 'e' changes the garbage data printed
in the border areas.
Bits b,c,d have effects when combined, as the following table
shows. Some of this information is a rehash of what was explained
above. Bits g,f,e will turn off sprites in all cases. (unless they
are already off to begin with)
Notes:
RI = regular intensity backdrop color
HI = half intensity backdrop color
A,B,S = Plane A, plane B, sprite layer
b c d Effect
----- ------
0 0 0 Display shown normally
0 0 1 B and S off, high priority pixels from B and S drawn in RI
0 1 0 A and B off, high priority pixels from A and S drawn in RI, sprites
have tile-shaped outline in RI.
0 1 1 Plane A pixels seem to be OR'd with plane B pixels, and the
output is OR'd with the sprite pixels.
1 0 0 A, B, and S off
1 0 1 B and S off, shadow/hilight mode off
1 1 0 A and B off, sprites have tile shaped outline in unknown color.
1 1 1 A and S off, shadow/hilight mode off
In mode 4, the same results apply with the following exceptions:
- Shadow/hilight processing is always off
- Anything that enables plane B seems to turn on a second graphics
layer, which is identical to plane A with garbage data. (so the VDP
can't really create two playfields in mode 4, but it does seem
to try to re-use plane A with bad graphics)
The settings which seem to enable plane B are when
bits b,c,d are 1,1,1, and and 0,1,1.
- The leftmost 8 pixels show a lot of garbage data when some of the
bits are set. (seems unrelated to sprites or background)
Earlier it was discovered that the VDP doesn't draw the background
tile in the left 8 pixels when the lower 3 bits of the horizontal
scroll value are not equal to zero, it shows garbage data that seems
to be based on the sprite positions. Also, this can be seen in the
rightmost 8 columns if you enable 40-cell mode while in mode 4, so
the resulting display is 320x192.

View File

@ -1,189 +0,0 @@
---------------------------------------
SSFII GENESIS TECHNICAL INFORMATION
Second Edition (July 26, 2000)
Bart Trzynadlowski
---------------------------------------
The purpose of this document is to discuss the workings of the Genesis port of
Capcom's "Super Street Fighter II The New Challengers". Virtually all of this
information was originally found by others' efforts.
Please credit "those who contributed information" rather than me if
you use any of this information. You may pass this document around freely, but
please keep it unaltered. If you see any errors or have more info, contact me.
I can be reached at trzy@powernet.net.
Second Edition: July 26, 2000
- Major update with correct information thanks to Tim Meekins
First Edition: July 21, 2000
- Initial release
0. THE SSFII CHALLENGE
The challenge behind getting "Super Street Fighter II The New Challengers"
(SSFII) to work on a Genesis emulator lies primarily in the fact that the game
is stored on a 40 megabit (5 megabyte) cartridge.
The Sega Genesis maps ROM from 0x000000 to 0x3FFFFF which means that
the CPU can only see 4 megabytes of cartridge ROM. SSFII needed more space for
the backgrounds and thus Capcom opted for a special 5 megabyte cartridge with
bankswitching in order to access the area of ROM outside of normal range.
1. THE BANKSWITCHING MECHANISM
The bankswitching mechanism probably resides on the cartridge. I'm 99% sure of
this. Sega documentation does offer a description of the mechanism, though,
which led me to suspect for a moment that perhaps the mechanism was on the
Genesis itself.
The idea is unlikely though, as that range of registers is used by the
32X for an entirely different purpose. I have been informed that that range
(which is marked as "SEGA RESERVED" in the Genesis developer's manual) can be
used for extra devices which may be present on the cartridge.
The bankswitching mechanism is very simple. It views the addressable 4 mega-
bytes of ROM as 8 512KB regions. The first area, 0x000000-0x07FFFF is fixed
and cannot be remapped because that is where the vector table resides.
The banking registers on the cartridge work by allocating the 512KB
chunk to a given part of the addressable 4MB ROM space. Below are the
registers and what range they correspond to. The value written to a register
will cause the specified 512KB page to be mapped to that region. A page is
specified with 6 bits (bits 7 and 6 are always 0) thus allowing a possible 64
pages (SSFII only has 10, though.)
0xA130F3: 0x080000 - 0x0FFFFF
0xA130F5: 0x100000 - 0x17FFFF
0xA130F7: 0x180000 - 0x1FFFFF
0xA130F9: 0x200000 - 0x27FFFF
0xA130FB: 0x280000 - 0x2FFFFF
0xA130FD: 0x300000 - 0x37FFFF
0xA130FF: 0x380000 - 0x3FFFFF
The registers are accessed through byte writes. I haven't seen SSFII try to
read any of the registers, so I don't know if it's possible or not. I don't
emulate anything besides byte writes in my emulator.
There is also a register 0xA130F1. Apparently the regions specified by
0xA130F9-0xA130FF (0x200000-0x3FFFFF) can be either ROM or RAM and can be
write-protected. Here is the layout of the register as far as I know:
7 6 5 4 3 2 1 0
+-----------------------+
|??|??|??|??|??|??|WP|MD|
+-----------------------+
MD: Mode -- 0 = ROM, 1 = RAM
WP: Write protect -- 0 = writable, 1 = not writable
Emulation of the 0xA130F1 register is not necessary, SSFII initializes it at
start-up by writing 0 I believe, which signifies ROM and no write protection
to the regions at 0x200000-0x3FFFFF (ROM isn't writable anyway, there isn't a
need for protection.)
Examples:
If 0x01 is written to register 0xA130FF, 0x080000-0x0FFFFF is visible
at 0x380000-0x3FFFFF.
If 0x08 is written to register 0xA130F9, the first 512KB of the
normally invisible upper 1MB of ROM is now visible at 0x200000-
0x27FFFF.
The registers simply represent address ranges in the 4MB ROM area and you can
page in data to these ranges by specifying the bank # -- it's that simple!
2. CHECKSUM
SSFII contains a checksum routine which calculates the checksum of the first
4MB of the ROM; it then pages in the last 1MB of ROM to 0x300000-0x3FFFFF.
It does this by writing to the bank registers. The following code is taken
directly from the US ROM dumped by Genesis Power:
... Checksum first 4MB of ROM (0x000000-0x3FFFFF) ...
0x003BEC: move.b #$08, ($A130FD)
0x003BF4: move.b #$09, ($A130FF)
0x003BFC: lea ($300000), a0
... Checksum uppper 1MB of ROM now mapped at 0x300000-0x3FFFFF ...
The bankswitching hardware must be properly emulated before the game starts
working. If it is not, the checksum will fail and the game will hang with a
red screen.
In the Genesis Power US dump, you can jump to 0x003C3C to avoid the
checksum routine, this is where program flow transfers to if the checksum was
found to be valid. The game doesn't do anything important before the checksum
code as far as emulation is concerned. It writes the SEGA message to the
Trademark Security System register and does some joypad init stuff.
3. EMULATING SSFII
SSFII is fairly straightforward to emulate. All you need to do is detect the
game, load up all 5MB, and emulate the banking registers. The easiest way to
do it, in my opinion, is to keep a second copy of the ROM and do memcpy()s
from that second copy to the ROM being emulated.
For example, here is how Genital does it... I've got genesis.rom which is the
buffer where ROMs are loaded and executed. There is also genesis.rom_ssf2
which is another 5MB buffer where I load the SSFII ROM to as well.
The bankswitching register emulation is done in my IOWriteByte()
function (which handles byte writes to the 0xA00000-0xBFFFFF range). The
following is the code I use:
if (addr >= 0xa130f3 && config.ssf2_emu)
{
switch (addr & 0xf)
{
case 0x3: /* 080000-0FFFFF */
memcpy((genesis.rom + 0x080000), (genesis.rom_ssf2 + (data * 0x80000)), 0x80000);
break;
case 0x5: /* 100000-17FFFF */
memcpy((genesis.rom + 0x100000), (genesis.rom_ssf2 + (data * 0x80000)), 0x80000);
break;
case 0x7: /* 180000-1FFFFF */
memcpy((genesis.rom + 0x180000), (genesis.rom_ssf2 + (data * 0x80000)), 0x80000);
break;
case 0x9: /* 200000-27FFFF */
memcpy((genesis.rom + 0x200000), (genesis.rom_ssf2 + (data * 0x80000)), 0x80000);
break;
case 0xb: /* 280000-2FFFFF */
memcpy((genesis.rom + 0x280000), (genesis.rom_ssf2 + (data * 0x80000)), 0x80000);
break;
case 0xd: /* 300000-37FFFF */
memcpy((genesis.rom + 0x300000), (genesis.rom_ssf2 + (data * 0x80000)), 0x80000);
break;
case 0xf: /* 380000-3FFFFF */
memcpy((genesis.rom + 0x380000), (genesis.rom_ssf2 + (data * 0x80000)), 0x80000);
break;
default:
break;
}
return;
}
Pardon the bad formatting, it just wouldn't fit correctly in the 80 columns
that the rest of the document sticks to.
The first line checks whether the address is 0xA130F3 or above (notice
how 0xA130F1 is ignored, SSFII doesn't really use it) and if SSFII emulation
is enabled (in Genital, I have a flag -- config.ssf2_emu -- which is set to 1
to indicate SSFII emulation should occur.) The remainder of the code is a
switch () statement which handles the register emulation.
Since 0x80000 = 512KB, and the data variable holds the byte written to
the register, data * 0x80000 yields the offset into the ROM that has been
requested to be mapped.
At first glance, memcpy()s may seem inefficient and slow. Although it
is true, this doesn't apply to emulating SSFII since the game doesn't do much
(if any) bankswitching during gameplay. No slowdown due to the memcpy()s is
noticable.
If you are using an emulator like Starscream which requires the ROMs to be
byteswapped, make certain both ROM images are byteswapped. If you don't use
2 copies of the ROM, you will find the game will still have several glitches
because the memcpy()s will be destroying the data they write over.
4. CONCLUSION
That's all there is to it. This should be sufficient information for anyone
wishing to implement SSFII support in their Sega Genesis emulator. If you have
any questions at all (I'm not great at making things clear) feel free to email
me at trzy@powernet.net.

View File

@ -1,152 +0,0 @@
Shadow / Hilight description
Version 0.1 (03/06/01)
by Charles MacDonald
WWW: http://cgfm2.emuviews.com
Unpublished work Copyright 2001 Charles MacDonald
Table of contents
1.) Introduction
2.) Color generation
3.) Backgrounds
4.) Sprites
5.) Overscan / border area
6.) Miscellaneous
7.) Games that use shadow / hilight mode
8.) Disclaimer
1.) Introduction
The shadow / hilight feature has never been properly documented, so here's
my attempt at doing just that.
I'd like to thank Flavio Morsoletto for sharing results from his
shadow / hilight tests.
2.) Color generation
As the VDP draws each pixel of the display, it uses the raw pattern data
and palette values to select an entry from CRAM, which is used to
create red, green, and blue values that define the color of the current
pixel being drawn.
In shadow / hilight mode, the VDP can do two things to the resulting pixel
color, either divide it's intensity (brightness) in half, or double it.
This is based on two factors, the priority level of the pixel, and the
values of the raw pattern and palette data.
In terms of how the colors are actually generated, imagine that each 3-bit
color value from CRAM is scaled up to fit a 0 to 63 range. Half intensity
colors would would range from 0 to 31, normal intensity colors would
range from 0 to 63, and double intensity colors would range from 32 to 63.
3.) Backgrounds
Low priority background tiles are shown at half intensity, high priority
background tiles are shown at normal intensity.
When the VDP renders high priority tiles, it does not take transparent
pixels into account. Instead, any underlying pixels (either from the
background, sprites, or backdrop) will be shown at normal intensity.
For example, if you had a completely transparent tile on plane B that
had it's priority bit set, any pixel from plane A or the sprite layer
that fell within the tile's 8x8 pixel area would be shown at normal
intensity.
4.) Sprites
Low priority sprites are shown at half intensity, high priority sprites
are shown at normal intensity. The priority values do not affect the
intensity of any overlapping sprites.
Any high-priority background tile will force a low-priority sprite to
be shown at normal intensity.
I'm going to call any sprite pixel that uses color 3Eh a hilight
operator, and any sprite pixel that uses color 3Fh a shadow operator.
Such pixels are not drawn by the VDP, but instead are treated as
transparent.
A shadow operator forces the underlying background or backdrop pixel
to be shown at half intensity, regardless of the pixel's priority.
A hilight operator forces the underlying background or backdrop pixel
to be shown at normal intensity if it is currently at half intensity,
or at double intensity if it is currently at normal intensity.
Operator pixels do not affect other sprites. In the case of operator
pixels overlapping, the first sprite in the sprite list is the one that
defines how the underlying background / backdrop pixel is modified.
5.) Overscan / border area
The backdrop is the entire display area (usually 256x224 pixels), which is
filled with the color value selected in VDP register #7. The background
layers and sprites are overlaid on top of the backdrop, so that any pixel
where no background or sprite pixels exist will show the backdrop color.
Overscan is the area outside of the physical display. You can see it if
you adjust the vertical or horizontal hold of a monitor to see past the
top/bottom or left/right edges of the screen.
When shadow / hilight mode is enabled, the overscan area is always
displayed at half intensity. The backdrop is also shown at half intensity,
but that can be modified by overlaying background tiles or sprites.
(either by priority, or by operator pixels)
If the display is blanked (bit 6 of VDP register #1) or the leftmost
column is blanked (bit 5 of VDP register #0), the portion of the display
in question has the same properties as the overscan area. (meaning
sprites and background tiles cannot affect it's intensity, it is
always fixed to half intensity)
6.) Miscellaneous
There is a bug in the way sprite pixel colors are processed by the VDP.
Color 0Eh of palettes 00-02h is always displayed at normal intensity,
regardless of the priority level of the sprite.
The contents of CRAM for colors 3Eh and 3Fh do not affect the shadow or
hilight effect. Though I've noticed many games set one or more of the
RGB values for either entry to maximum, like 0EEEh or 0E0Eh.
For those of you who want some statistics, the Genesis VDP can display 61
of 512 colors normally, and 183 of 1536 colors in shadow / hilight mode.
That doesn't include duplicate colors, which may or may not exist.
7.) Games that use shadow / hilight mode
- Adventures of Batman & Robin
- Ecco 2 : The Tides of Time
- Gauntlet IV
- Mega Turrican
- Mortal Kombat
- Shinobi III
- Skeleton Krew
- Sonic 2
- Sonic 3, Sonic & Knuckles
- Sonic 3D Blast
- Space Harrier II
- Sub Terrania
- Red Zone
- Ranger-X
8.) Disclaimer
If you use any information from this document, please credit me
(Charles MacDonald) and optionally provide a link to my webpage
(http://cgfm2.emuviews.com/) so interested parties can access it.
The credit text should be present in the accompanying documentation of
whatever project which used the information, or even in the program
itself (e.g. an about box)
Regarding distribution, you cannot put this document on another
website, nor link directly to it.

View File

@ -1,26 +0,0 @@
Here's the format of the YM2612 test register ($21), as best as I can
tell:
bit 7 - If bit 6 set, select 0=LSB, 1=MSB of serial data
bit 6 - If set, reading status returns serial data LSB or MSB instead of
status flags
bit 5 - If set, only the attack phase and possibly decay occur, there is
no sustain o release. It sounds like each channel was keyed-on rapidly.
When the bit is cleared, the channels resume their original position
within the envelope so this bit doesn't have any lasting change on
them.
bit 4 - Data sent to DAC is inverted - this is *really* loud, so turn
down the volume before using this bit. ;)
bit 3 - Audio output is muted, (the PSG still works of course) bits 4,5
will make sound faintly audible when set in conjunction.
bit 2 - Timer A and B run 24 times faster.
bits 1,0 - No effect.
Bits 7, 6 allow you to read the serial data sent from the YM2612 to the
DAC. (the other chip, YM3012 - not the DAC at $2A/$2B) I'm unsure of the
exact format, it's probably similar to the YM2151. Bit 4 inverts the
data sent to the DAC, but not the data read from the status register.
Compared to the YM2151 test register documented in MAME, the last 3 bits
may have something to do with the LFO. And I'm also not entirely sure
about the MSB/LSB order for bit 6. Other than that the two work in a
mostly identical way.

View File

@ -1,149 +1,149 @@
The Genesis Plus Project
------------------------------
CHANGELOG:
- completely rewrote EEPROM emulation: now support all known EEPROM types (24C01-24C65) and mappers (Sega, Acclaim, EA, Codemasters)
used in a few games (now use game database) as backup RAM. This should fix SRAM load/save support in the following games:
. NBA Jam (alternate Acclaim mapper)
. College Slam, Frank Thomas Big Hurt Baseball (24C65 type)
. NHLPA Hockey 93, Rings of Power (EA mapper)
. Micromachines games (Codemasters mapper)
- modified SRAM initialization with 0xFF data: fix Micromachines 2, Dino Dini Soccer
- fixed SRAM word read/write handler: fix some Sega Sports and EA Sports games (NFL95, NBA Action 95, NL97, NHL98,...) which previously hang
- modified WRITE_xxx & READ_xxx macros for portability
- rewrote BIG ENDIAN support in render.c and vdp.c: it should be a little faster now (no more useless swapping)
- fixed leftmost Window/PlaneA column render and implemented Window bug (as described in gen-vdp.txt)
- improved Sprite Limit emulation and Sprite Collision detection
- fixed test made before CRAM writes
- removed redundant "color_update()" calls
- added 9bits (RGB333) pixel color extrapolation to cover full color range (0-31;0-63) in 16-bit rendering mode (RGB565)
- rewrote Interrupts handling: Sesame's Street Counting Cafe now works without any hacks, other timing sensitive games seems not to be affected
- modified Hcounter tables: Road Rash games (I,II,III) don't need any timing hacks anymore
- fixed VDP latency so it does not interfere with DMA timings anymore
20/07/2007:
[Genesis]
- corrected TeamPlayer support: fix multiplayer in Gauntlet 4 (Sept. version), Pengo and a lot of others
- added J-Cart support: enable multiplayer in Codemasters games (Pete Sampras, Micromachines games, Super Skidmarks)
- added serial EEPROM autodetection: fix games with bad SRAM informations in header (NBA Jam TE)
- added SVP faking: display 2D graphics in Virtua Racing (the game is however still unplayable)
- added support for more internal IO registers: fixe some unlicensed games (Wisdom Tree games...)
- added preliminary support for unmapped protection device: fix some unlicensed games with special built-in hardware (Squirell King, Lion King 2...)
- added "Soft Reset" combo (in game, use L+Z triggers): this should be like pressing the RESET button on a real Genesis and this is required
in some games to enable special features or even complete the game (ex: X-Men).
[NGC]
- added separate configuration for PortA/PortB inputs (GAMEPAD, MULTITAP or NONE, see Joypad Config): this let you setting
PORTB as unplugged, which is needed in some games to access special modes or enable cheat codes (Alien Storm, X-Men...)
- Freezestate & SRAM files are now compressed (using zlib)
- FreezeState & SRAM files can now be saved/loaded to/from SDCARD: located in /genplus/saves/ from the root of your SDCARD
- changed initial ROMS directory for SDCARD user: now looking for /genplus/roms/ from the root of your SDCARD
- added user-transparent SRAM autoload (detection order is MCARD then SDCARD, SLOTA then SLOTB)
- "System reboot" is now used for console reboot and SD/PSO reload (if detected)
- added new font: now use original IPL font, extracted from Bootrom
- modified controls when going into the rom selection menu (DVD or SDCARD):
. use B button to go up one directory
. use Z button to quit the file selection menu
. use L/R triggers to go down/up one full page
. use Left/Right buttons or Analog stick to scroll the selected entry's filename when it can't be full displayed
- various menu rearrangment, minor bugfixes & sourcecode cleanup
21/06/2007:
- added 4.7GB DVD support for WII drives (the maximal allowed size for Gamecube DVD is still 1.35GB)
- removed MPAL video timings, always use 60Hz NTSC: fix display problems for PAL wii users (no more PAL50 version needed)
- added Console Reboot option in main menu (IPL Reboot)
- added Multitap support (EA 4-Way Play and Sega Teamplayer): allowed up to four players in games supporting those peripherals
- added partial Sega Menacer lightgun support (use Analog Stick): automatically set when detecting the 6-in-1 Menacer game
18/05/2007:
- you can now switch between FM cores without reseting the game. FM registers value are automatically restored when switching.
- modified PAL framesync a little bit: the 20ms period is now applied between the start of 2 consecutive frames,
no more between the end of the previous and the start of the next one, which seems more correct to me
- removed the previous VINT timings modification because it brokes some games (Rocket Knight, Thunderforce III,...)
- added automatic Timing configuration (VDP latency, VINT timing & alternate Line Timing) at game loading, based upon specific romname detection.
This means you can still modify some of these options afterwards but they are now automatically set/unset when loading a game which need
special timing fixes. These fixes are also automatically desactivated when the current game doesn't need them.
For your information, games that are actually detected and need special timings to run properly are:
.Legend of Galahad & Road Rash series (single line not rendered properly)
.Sesame Street Counting Cafe (don't boot)
.Chaos Engine/Soldiers of Fortune (graphic glitches on scrolling)
08/05/2007:
- corrected L & R buttons assignment: fixes Genesis X & Z buttons being inverted
- VINT timings are now a little more accurate: fixes Sesame's Street Counting Cafe
- SN76496 MAX_OUTPUT back to normal
- modified FB_WNOISE value in SN76496 core according to John Kortink's last informations
- added support for Maxim's PSG core, same as used in SMSPLUS (it becomes the default PSG core)
- updated FM core to the latest MAME version
- corrected DAC output level (fixes voices and some special FX being too low)
- added support for Gens YM2612 (FM) core (MAME's one still remains default FM core)
- added configurable preamplification for each sound cores (see Emulator Options)
- added some other configurable sound options (boost overall volume, FM improvment for Gens YM2612)
11/04/2007:
- corrected MAX_OUTPUT value in SN76496 core: fix PSG sound (SFX) volume
- removed unused sound buffer allocation
26/03/2007:
- added DVD automount: automatically call libogc DVD_Mount function if ISO PVD reading failed (idea taken from softdev's last neocdredux release). This may be useful for loading roms from a DVD after booting from SDLOAD or after stopping DVD motor.
- added "DVD motor off" feature, like in others emulators
- corrected Memory Card mounting function: EXI_ProbeReset() function was never called if the first mounting attempt failed. Should fix some of the "Unable to mount memory card" errors.
22/03/2007:
- added SDCARD subdirectory browsing and LFN (255 char. max) support
17/03/2007:
- remove some rendering unused code (only used by DOS version of genesis plus) for little speedup
- added an option to enable alternate line rendering timing (fix single line error in Road Rash series and Legend of Galahad's Intro)
- Color RAM update now always reset color 0 to border color (fix color glitches in Mortal Kombat,...) (thanks to Noop's for the idea)
- added last Softdev's modifications (normalised memory access and ASM GU functions used intead of 'C' ones) for some speedup
- updated gcaram.c to be compatible with last libogc version
09/03/2007:
- little rendering code speedups
- modified HV counter tables (fix graphic glitches in Skitchin's sky, Lotus 2 Recs, Panorama Cotton, Dashin Desperados & maybe more)
- completely rewrote DMA timings emulation so that it works for all games (no more cpu freezing)
- added all DMA tranfer rates handling for each three DMA modes and added dma busy flag emulation
- modified interrupts handling on VDP register #0 and #1 writes (fix Lemmings status bar)
- added VDP RAM write latency (fix Chaos Engine/Soldier of Fortune gfx glitches)
- modified FM timers handling a bit (fix Vectorman2 music)
- corrected Sprite Limit rendering (fix Sonic 1 & Micromachines 2 title screens)
- corrected IO Registers writes (fix Decap' Attack controls, no more need for alternate input)
- corrected 6 Buttons Pad emulation (fix 6buttons detection in Mortal Kombat 3, Comix Zone and other 6-buttons compatible games)
- modified sound mixing a bit according to Generator sourcecode (FM and PSG ratios seems more correct)
- added separate CPU Region (USA, Europe, Japan,...) & Speed (PAL or NTSC) choice in menu options
- modified main frame synchro in PAL mode (fix sound glitch in this mode), thanks to Softdev for the solution
- added savestates support (go to SRAM menu, memory card supports only)
07/02/2007: (Eke-Eke)
- fm timers fixed (fix missing music in Castle of Illusion, Quackshot, Undead Line, Wonderboy in Monster Lair, Cal 50, Turbo Outrun, Thundeforce 4 and maybe more)
- added complete EEPROM emulation (save support now works fine in Wonderboy5, Megaman Willy Wars, NBA Jam...) (credits to Notaz, adapted from Picodrive code)
- added preliminar dma timing emulation (fix bottom screen in Legend of Galahad) (credits to Notaz, adapted from Picodrive code)
- hack: clear Vint pending after Hint (INT level 4) acknowledge (fix Fatal Rewind)
- hack: modify read_bus16 to return a random value (fake fetch) (fix Time Killers)
- modified cpu execution timings, with more correct hblank and interrupts timing (fix ISS Deluxe, Double Dragon 2 and certainly more) (Based on Gens code)
- modified busreq mechanism: better synchro between z80 & 68k (no need to dejitter anymore) (Based on Gens code)
- added sprite collision detection (fix Strider 2)
- modified dma fill operation for big endian platform (fix Contra Hardcorps gfx garbage)
Based on Softdev's initial releases
WIP1.2 unzip.c
Added partial zip support
WIP1.1 sio.c added
Added six button pad support from x86 Gens
Additional changes based on Charles MacDonald's gen-hw.txt
WIP1 07 March 2006
Updated SN76496 driver
Genesis Plus for Gamecube
------------------------------
CHANGELOG:
- completely rewrote EEPROM emulation: now support all known EEPROM types (24C01-24C65) and mappers (Sega, Acclaim, EA, Codemasters)
used in a few games (now use game database) as backup RAM. This should fix SRAM load/save support in the following games:
. NBA Jam (alternate Acclaim mapper)
. College Slam, Frank Thomas Big Hurt Baseball (24C65 type)
. NHLPA Hockey 93, Rings of Power (EA mapper)
. Micromachines games (Codemasters mapper)
- SRAM is now initialized with 0xFF data: fix Micromachines 2, Dino Dini Soccer
- fixed SRAM word read/write handler: fix some Sega Sports and EA Sports games (NFL95, NBA Action 95, NL97, NHL98,...) which previously hang
- modified WRITE_xxx & READ_xxx macros for portability
- rewrote BIG ENDIAN support in render.c and vdp.c: it should be a little faster now (no more useless swapping)
- fixed leftmost Window/PlaneA column render and implemented Window bug (as described in gen-vdp.txt)
- improved Sprite Limit emulation and Sprite Collision detection
- fixed test made before CRAM writes
- removed redundant "color_update()" calls
- added 9bits (RGB333) pixel color extrapolation to cover full color range (0-31;0-63) in 16-bit rendering mode (RGB565)
- rewrote Interrupts handling: Sesame's Street Counting Cafe now works without any hacks, other timing sensitive games seems not to be affected
- modified Hcounter tables: Road Rash games (I,II,III) don't need any timing hacks anymore
- fixed VDP latency so it does not interfere with DMA timings anymore
20/07/2007:
[Genesis]
- corrected TeamPlayer support: fix multiplayer in Gauntlet 4 (Sept. version), Pengo and a lot of others
- added J-Cart support: enable multiplayer in Codemasters games (Pete Sampras, Micromachines games, Super Skidmarks)
- added serial EEPROM autodetection: fix games with bad SRAM informations in header (NBA Jam TE)
- added SVP faking: display 2D graphics in Virtua Racing (the game is however still unplayable)
- added support for more internal IO registers: fixe some unlicensed games (Wisdom Tree games...)
- added preliminary support for unmapped protection device: fix some unlicensed games with special built-in hardware (Squirell King, Lion King 2...)
- added "Soft Reset" combo (in game, use L+Z triggers): this should be like pressing the RESET button on a real Genesis and this is required
in some games to enable special features or even complete the game (ex: X-Men).
[NGC]
- added separate configuration for PortA/PortB inputs (GAMEPAD, MULTITAP or NONE, see Joypad Config): this let you setting
PORTB as unplugged, which is needed in some games to access special modes or enable cheat codes (Alien Storm, X-Men...)
- Freezestate & SRAM files are now compressed (using zlib)
- FreezeState & SRAM files can now be saved/loaded to/from SDCARD: located in /genplus/saves/ from the root of your SDCARD
- changed initial ROMS directory for SDCARD user: now looking for /genplus/roms/ from the root of your SDCARD
- added user-transparent SRAM autoload (detection order is MCARD then SDCARD, SLOTA then SLOTB)
- "System reboot" is now used for console reboot and SD/PSO reload (if detected)
- added new font: now use original IPL font, extracted from Bootrom
- modified controls when going into the rom selection menu (DVD or SDCARD):
. use B button to go up one directory
. use Z button to quit the file selection menu
. use L/R triggers to go down/up one full page
. use Left/Right buttons or Analog stick to scroll the selected entry's filename when it can't be full displayed
- various menu rearrangment, minor bugfixes & sourcecode cleanup
21/06/2007:
- added 4.7GB DVD support for WII drives (the maximal allowed size for Gamecube DVD is still 1.35GB)
- removed MPAL video timings, always use 60Hz NTSC: fix display problems for PAL wii users (no more PAL50 version needed)
- added Console Reboot option in main menu (IPL Reboot)
- added Multitap support (EA 4-Way Play and Sega Teamplayer): allowed up to four players in games supporting those peripherals
- added partial Sega Menacer lightgun support (use Analog Stick): automatically set when detecting the 6-in-1 Menacer game
18/05/2007:
- you can now switch between FM cores without reseting the game. FM registers value are automatically restored when switching.
- modified PAL framesync a little bit: the 20ms period is now applied between the start of 2 consecutive frames,
no more between the end of the previous and the start of the next one, which seems more correct to me
- removed the previous VINT timings modification because it brokes some games (Rocket Knight, Thunderforce III,...)
- added automatic Timing configuration (VDP latency, VINT timing & alternate Line Timing) at game loading, based upon specific romname detection.
This means you can still modify some of these options afterwards but they are now automatically set/unset when loading a game which need
special timing fixes. These fixes are also automatically desactivated when the current game doesn't need them.
For your information, games that are actually detected and need special timings to run properly are:
.Legend of Galahad & Road Rash series (single line not rendered properly)
.Sesame Street Counting Cafe (don't boot)
.Chaos Engine/Soldiers of Fortune (graphic glitches on scrolling)
08/05/2007:
- corrected L & R buttons assignment: fixes Genesis X & Z buttons being inverted
- VINT timings are now a little more accurate: fixes Sesame's Street Counting Cafe
- SN76496 MAX_OUTPUT back to normal
- modified FB_WNOISE value in SN76496 core according to John Kortink's last informations
- added support for Maxim's PSG core, same as used in SMSPLUS (it becomes the default PSG core)
- updated FM core to the latest MAME version
- corrected DAC output level (fixes voices and some special FX being too low)
- added support for Gens YM2612 (FM) core (MAME's one still remains default FM core)
- added configurable preamplification for each sound cores (see Emulator Options)
- added some other configurable sound options (boost overall volume, FM improvment for Gens YM2612)
11/04/2007:
- corrected MAX_OUTPUT value in SN76496 core: fix PSG sound (SFX) volume
- removed unused sound buffer allocation
26/03/2007:
- added DVD automount: automatically call libogc DVD_Mount function if ISO PVD reading failed (idea taken from softdev's last neocdredux release). This may be useful for loading roms from a DVD after booting from SDLOAD or after stopping DVD motor.
- added "DVD motor off" feature, like in others emulators
- corrected Memory Card mounting function: EXI_ProbeReset() function was never called if the first mounting attempt failed. Should fix some of the "Unable to mount memory card" errors.
22/03/2007:
- added SDCARD subdirectory browsing and LFN (255 char. max) support
17/03/2007:
- remove some rendering unused code (only used by DOS version of genesis plus) for little speedup
- added an option to enable alternate line rendering timing (fix single line error in Road Rash series and Legend of Galahad's Intro)
- Color RAM update now always reset color 0 to border color (fix color glitches in Mortal Kombat,...) (thanks to Noop's for the idea)
- added last Softdev's modifications (normalised memory access and ASM GU functions used intead of 'C' ones) for some speedup
- updated gcaram.c to be compatible with last libogc version
09/03/2007:
- little rendering code speedups
- modified HV counter tables (fix graphic glitches in Skitchin's sky, Lotus 2 Recs, Panorama Cotton, Dashin Desperados & maybe more)
- completely rewrote DMA timings emulation so that it works for all games (no more cpu freezing)
- added all DMA tranfer rates handling for each three DMA modes and added dma busy flag emulation
- modified interrupts handling on VDP register #0 and #1 writes (fix Lemmings status bar)
- added VDP RAM write latency (fix Chaos Engine/Soldier of Fortune gfx glitches)
- modified FM timers handling a bit (fix Vectorman2 music)
- corrected Sprite Limit rendering (fix Sonic 1 & Micromachines 2 title screens)
- corrected IO Registers writes (fix Decap' Attack controls, no more need for alternate input)
- corrected 6 Buttons Pad emulation (fix 6buttons detection in Mortal Kombat 3, Comix Zone and other 6-buttons compatible games)
- modified sound mixing a bit according to Generator sourcecode (FM and PSG ratios seems more correct)
- added separate CPU Region (USA, Europe, Japan,...) & Speed (PAL or NTSC) choice in menu options
- modified main frame synchro in PAL mode (fix sound glitch in this mode), thanks to Softdev for the solution
- added savestates support (go to SRAM menu, memory card supports only)
07/02/2007: (Eke-Eke)
- fm timers fixed (fix missing music in Castle of Illusion, Quackshot, Undead Line, Wonderboy in Monster Lair, Cal 50, Turbo Outrun, Thundeforce 4 and maybe more)
- added complete EEPROM emulation (save support now works fine in Wonderboy5, Megaman Willy Wars, NBA Jam...) (credits to Notaz, adapted from Picodrive code)
- added preliminar dma timing emulation (fix bottom screen in Legend of Galahad) (credits to Notaz, adapted from Picodrive code)
- hack: clear Vint pending after Hint (INT level 4) acknowledge (fix Fatal Rewind)
- hack: modify read_bus16 to return a random value (fake fetch) (fix Time Killers)
- modified cpu execution timings, with more correct hblank and interrupts timing (fix ISS Deluxe, Double Dragon 2 and certainly more) (Based on Gens code)
- modified busreq mechanism: better synchro between z80 & 68k (no need to dejitter anymore) (Based on Gens code)
- added sprite collision detection (fix Strider 2)
- modified dma fill operation for big endian platform (fix Contra Hardcorps gfx garbage)
Based on Softdev's initial releases
WIP1.2 unzip.c
Added partial zip support
WIP1.1 sio.c added
Added six button pad support from x86 Gens
Additional changes based on Charles MacDonald's gen-hw.txt
WIP1 07 March 2006
Updated SN76496 driver
Added GX Hardware Scaling