mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-11-04 18:05:06 +01:00
added documentation
This commit is contained in:
parent
1bb58b69b9
commit
f76f955ec7
@ -0,0 +1,373 @@
|
||||
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!
|
@ -0,0 +1,74 @@
|
||||
|
||||
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.
|
||||
|
238
source/docs/eeprom.txt
Normal file
238
source/docs/eeprom.txt
Normal file
@ -0,0 +1,238 @@
|
||||
-------------------------------------------------------
|
||||
ACCLAIM (81)
|
||||
-------------------------------------------------------
|
||||
|
||||
NBA Jam (UE)
|
||||
NBA Jam (J)
|
||||
------------
|
||||
T-081326
|
||||
T-81033
|
||||
header OK ($200001-$200001)
|
||||
|
||||
TYPE: 8BITS WORD ADDRESS
|
||||
SIZE_MASK: 0xFF (24C02)
|
||||
PAGE_MASK: 0x03
|
||||
SDA_IN : 0x200000 (0)
|
||||
SDA_OUT: 0x200000 (1)
|
||||
SCL : 0x200000 (1)
|
||||
|
||||
Note: this game uses a different EEPROM mapper than other Accolade games.
|
||||
|
||||
|
||||
Blockbuster World Video Game Championship II (U)
|
||||
NBA Jam Tournament Edition (JUE)
|
||||
------------------------------------------------
|
||||
T-81406
|
||||
header KO
|
||||
|
||||
TYPE: TYPE: 8BITS WORD ADDRESS
|
||||
SIZE_MASK: 0xFF (24C02)
|
||||
PAGE_MASK: 0x03
|
||||
SDA_IN : 0x200001 (0)
|
||||
SDA_OUT: 0x200001 (0)
|
||||
SCL : 0x200000 (0)
|
||||
|
||||
Note: Rev 00 of the game has buggy eeprom support (incorrect data written), game backup only work with Rev01 version (released apparently in 2002, eight years later !)
|
||||
|
||||
|
||||
NFL Quarterback Club (JUE)
|
||||
-----------------------------
|
||||
T-081276
|
||||
header OK ($200000-$200001)
|
||||
|
||||
TYPE: TYPE: 8BITS WORD ADDRESS
|
||||
SIZE_MASK: 0xFF (24C02)
|
||||
PAGE_MASK: 0x03
|
||||
SDA_IN : 0x200001 (0)
|
||||
SDA_OUT: 0x200001 (0)
|
||||
SCL : 0x200000 (0)
|
||||
|
||||
|
||||
NFL Quarterback Club 96 (UE)
|
||||
-----------------------------
|
||||
T-081586
|
||||
header OK ($200000-$200001)
|
||||
|
||||
TYPE: TYPE: 8BITS WORD ADDRESS
|
||||
SIZE_MASK: 0x7FF (24C16)
|
||||
PAGE_MASK: 0x07
|
||||
SDA_IN : 0x200001 (0)
|
||||
SDA_OUT: 0x200001 (0)
|
||||
SCL : 0x200000 (0)
|
||||
|
||||
|
||||
College Slam (U)
|
||||
----------------
|
||||
T-81576
|
||||
header OK ($200001-$200001)
|
||||
|
||||
TYPE: 16BITS WORD ADDRESS
|
||||
SIZE_MASK: 0x1FFF (24C64)
|
||||
PAGE_MASK: 0x07
|
||||
SDA_IN : 0x200001 (0)
|
||||
SDA_OUT: 0x200001 (0)
|
||||
SCL : 0x200000 (0)
|
||||
|
||||
|
||||
Frank Thomas Big Hurt Baseball (UE)
|
||||
----------------
|
||||
T-81476
|
||||
header OK ($200000-$200001)
|
||||
|
||||
TYPE: 16BITS WORD ADDRESS
|
||||
SIZE_MASK: 0x1FFF (24C64)
|
||||
PAGE_MASK: 0x07
|
||||
SDA_IN : 0x200001 (0)
|
||||
SDA_OUT: 0x200001 (0)
|
||||
SCL : 0x200000 (0)
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------
|
||||
CAPCOM (12)
|
||||
-------------------------------------------------------
|
||||
|
||||
Megaman - The Wily Wars (E)
|
||||
Rockman Mega World (J) [alt]
|
||||
----------------
|
||||
T-12046
|
||||
T-12053 (checksum = 0xEA80)
|
||||
header OK ($200001-$200001)
|
||||
|
||||
TYPE: 7BITS WORD ADDRESS
|
||||
SIZE_MASK: 0x7F (24C01)
|
||||
PAGE_MASK: 0x03
|
||||
SDA_IN : 0x200001 (0)
|
||||
SDA_OUT: 0x200001 (0)
|
||||
SCL : 0x200001 (1)
|
||||
|
||||
NOTE: the original version of Rockman Mega World (J) uses traditional SRAM, header gives $200000-$203FFF range
|
||||
the alternate version uses a 128bytes serial EEPROM (X24C01)
|
||||
the two versions share the same GAME NAME and PRODUCT ID
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------
|
||||
Electronic Arts (50)
|
||||
-------------------------------------------------------
|
||||
|
||||
NHLPA Hockey 93 (UE)
|
||||
----------------
|
||||
T-50396
|
||||
header KO
|
||||
|
||||
TYPE: 7BITS WORD ADDRESS
|
||||
SIZE_MASK: 0x7F (24C01)
|
||||
PAGE_MASK: 0x03
|
||||
SDA_IN : 0x200000 (7)
|
||||
SDA_OUT: 0x200000 (7)
|
||||
SCL : 0x200000 (6)
|
||||
|
||||
|
||||
Rings of Power (UE)
|
||||
----------------
|
||||
T-50176
|
||||
header KO
|
||||
|
||||
TYPE: 7BITS WORD ADDRESS
|
||||
SIZE_MASK: 0x7F (24C01)
|
||||
PAGE_MASK: 0x03
|
||||
SDA_IN : 0x200000 (7)
|
||||
SDA_OUT: 0x200000 (7)
|
||||
SCL : 0x200000 (6)
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------
|
||||
SEGA
|
||||
-------------------------------------------------------
|
||||
|
||||
Evander 'Real Deal' Holyfield's Boxing (JUE)
|
||||
----------------------------------
|
||||
MK-1215
|
||||
header OK ($200001-$200001)
|
||||
|
||||
TYPE: 7BITS WORD ADDRESS
|
||||
SIZE_MASK: 0x7F (24C01)
|
||||
PAGE_MASK: 0x03
|
||||
SDA_IN : 0x200001 (0)
|
||||
SDA_OUT: 0x200001 (0)
|
||||
SCL : 0x200001 (1)
|
||||
|
||||
|
||||
Greatest Heavyweights of the Ring (U)
|
||||
Greatest Heavyweights of the Ring (J)
|
||||
Greatest Heavyweights of the Ring (E)
|
||||
-----------------------------
|
||||
MK-1228
|
||||
G-5538
|
||||
PR-1993
|
||||
header OK ($200001-$200001)
|
||||
|
||||
TYPE: 7BITS WORD ADDRESS
|
||||
SIZE_MASK: 0x7F (24C01)
|
||||
PAGE_MASK: 0x03
|
||||
SDA_IN : 0x200001 (0)
|
||||
SDA_OUT: 0x200001 (0)
|
||||
SCL : 0x200001 (1)
|
||||
|
||||
|
||||
Wonder Boy in Monster World (UE)
|
||||
Wonder Boy V - Monster World III (J)
|
||||
----------------
|
||||
G-4060
|
||||
header OK ($200001-$200001)
|
||||
|
||||
TYPE: 7BITS WORD ADDRESS
|
||||
SIZE_MASK: 0x7F (24C01)
|
||||
PAGE_MASK: 0x03
|
||||
SDA_IN : 0x200001 (0)
|
||||
SDA_OUT: 0x200001 (0)
|
||||
SCL : 0x200001 (1)
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------
|
||||
CODEMASTERS
|
||||
-------------------------------------------------------
|
||||
|
||||
Micro Machines 2 - Turbo Tournament (E) (J-Cart)
|
||||
------------------------------------------------
|
||||
T-120096-50
|
||||
header KO
|
||||
|
||||
TYPE: TYPE: 8BITS WORD ADDRESS
|
||||
SIZE_MASK: 0x3FF (24C08)
|
||||
PAGE_MASK: 0x0F
|
||||
SDA_IN : 0x300000 (0)
|
||||
SDA_OUT: 0x380001 (7)
|
||||
SCL : 0x300000 (1)
|
||||
|
||||
Note: this game needs the EEPROM to be initially fullfilled with the string
|
||||
"PETETEST01234567" otherwise it won't initialize memory with correct data.
|
||||
|
||||
|
||||
Micro Machines Military (E) (J-Cart)
|
||||
------------------------------------
|
||||
00000000-00 (checksum = 0x168B or 0xCEE0)
|
||||
header KO
|
||||
|
||||
TYPE: TYPE: 8BITS WORD ADDRESS
|
||||
SIZE_MASK: 0x3FF (24C08)
|
||||
PAGE_MASK: 0x0F
|
||||
SDA_IN : 0x300000 (0)
|
||||
SDA_OUT: 0x380001 (7)
|
||||
SCL : 0x300000 (1)
|
||||
|
||||
|
||||
Micro Machines Turbo Tournament 96 (E) (J-Cart)
|
||||
------------------------------------------------
|
||||
00000000-00 (checksum = 0x165E or 0x2C41)
|
||||
header KO
|
||||
|
||||
TYPE: TYPE: 8BITS WORD ADDRESS
|
||||
SIZE_MASK: 0x7FF (24C16)
|
||||
PAGE_MASK: 0xF
|
||||
SDA_IN : 0x300000 (0)
|
||||
SDA_OUT: 0x380001 (7)
|
||||
SCL : 0x300000 (1)
|
458
source/docs/gennotes.txt
Normal file
458
source/docs/gennotes.txt
Normal file
@ -0,0 +1,458 @@
|
||||
******************************************************
|
||||
* 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.
|
||||
|
||||
|
312
source/docs/gensave.txt
Normal file
312
source/docs/gensave.txt
Normal file
@ -0,0 +1,312 @@
|
||||
----------------------------------------------
|
||||
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.
|
@ -0,0 +1,40 @@
|
||||
|
||||
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.
|
||||
|
@ -0,0 +1,89 @@
|
||||
|
||||
Introduction
|
||||
|
||||
Genesis Plus has reasonable speed, and very fast rendering. Here are some
|
||||
details about porting it to another platform
|
||||
|
||||
Porting rules
|
||||
|
||||
- This program is released under the GPL, so please release the source
|
||||
code for your derivative ports. Let me know if you need an alternative
|
||||
to this.
|
||||
|
||||
- Do not change the name of the emulator. Something like 'Genesis Plus / MacOS'
|
||||
is fine as it keeps the original name.
|
||||
|
||||
- Configure the CPU emulators for little or big-endian CPUs, and use the
|
||||
ALIGN_LONG option to handle unaligned memory accesses if needed. E.g. if
|
||||
the emulator crashes when a game scrolls horizontally, you need to enable
|
||||
it.
|
||||
|
||||
Requirements
|
||||
|
||||
- At this time the 16-bit rendering code has been well tested and should
|
||||
be used. There is code to support 8 through 32-bit displays, but I
|
||||
haven't checked if it still works.
|
||||
|
||||
- Audio output, if enabled, uses stereo 16-bit samples.
|
||||
|
||||
Functions to use:
|
||||
|
||||
int load_rom(char *filename);
|
||||
|
||||
Loads a game which can be in BIN, SMD or ZIP formats. It returns zero if
|
||||
an error has occured.
|
||||
|
||||
void system_init(void);
|
||||
|
||||
Initializes the virtual Genesis console. Call this once during startup.
|
||||
|
||||
void audio_init(int rate);
|
||||
|
||||
Initialize the sound emulation part of the emulator. Pass zero or don't
|
||||
call the function to disable sound. Call this after running system_init().
|
||||
|
||||
void system_reset(void);
|
||||
|
||||
Resets the virtual Genesis console. Call this once during setup, and later
|
||||
as needed.
|
||||
|
||||
int system_frame(int skip);
|
||||
|
||||
Updates the emulation for a frame. Pass 1 to prevent rendering (which can
|
||||
be used for frame skipping) and 0 to render the current display.
|
||||
|
||||
This function returns 0 if the virtual Genesis console has locked up.
|
||||
You can do what you'd like with this information, such as notify the user,
|
||||
reset the machine, etc.
|
||||
|
||||
If audio is enabled, the snd.buffer[] array will hold the current audio
|
||||
data for this frame.
|
||||
|
||||
void system_shutdown(void);
|
||||
|
||||
Shuts down the emulator.
|
||||
|
||||
Variables:
|
||||
|
||||
The 'bitmap' structure needs to be filled out prior to calling system_init().
|
||||
This provides the rendering code with information about the type of bitmap
|
||||
it is rendering to. I would advise sticking with a 1024x512 16-bit bitmap:
|
||||
|
||||
memset(&bitmap, 0, sizeof(t_bitmap));
|
||||
bitmap.width = 1024;
|
||||
bitmap.height = 512;
|
||||
bitmap.depth = 16;
|
||||
bitmap.granularity = 2; /* Bytes per pixel */
|
||||
bitmap.pitch = (bitmap.width * bitmap.granularity);
|
||||
bitmap.data = (unsigned char *)bmp->pixels; /* Pointer to your bitmap */
|
||||
bitmap.viewport.w = 256; /* Initial size of display on power-up (do not change) */
|
||||
bitmap.viewport.h = 224;
|
||||
bitmap.viewport.x = 0x20; /* Offset used for rendering (do not change) */
|
||||
bitmap.viewport.y = 0x00;
|
||||
bitmap.remap = 1;
|
||||
|
||||
The variable 'input.pad[0]' holds the button states for the first player
|
||||
gamepad. Update this prior to calling system_frame(), and use the bitmasks
|
||||
defined in system.h such as 'INPUT_UP', etc.
|
||||
|
||||
See the Windows/SDL and DOS drivers for examples.
|
@ -0,0 +1,122 @@
|
||||
----------------------------------------------------------------------------
|
||||
Genesis Plus
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Version 1.2a
|
||||
by Charles Mac Donald
|
||||
WWW: http://cgfm2.emuviews.com
|
||||
|
||||
What's New
|
||||
----------
|
||||
|
||||
[06/22/03]
|
||||
- Modified rendering code for portability
|
||||
- Modified memory handling to fix banked PSG access
|
||||
[05/13/03]
|
||||
- Initial release
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The Windows version runs windowed in a 16-bit desktop with NO sound or
|
||||
joystick support.
|
||||
|
||||
The DOS version has most of the functionality from SMS Plus, such
|
||||
as audio, joysticks, etc.
|
||||
|
||||
Windows/DOS controls:
|
||||
|
||||
Arrow Keys - Directional pad
|
||||
A,S,D,F - 1P gamepad, buttons A, B, C, Start
|
||||
Tab - Reset
|
||||
Esc - Exit program
|
||||
|
||||
DOS only:
|
||||
|
||||
End - Exit program
|
||||
F1-F4 - Set frameskip level (F1 = no skip ... F4 = skip 3 frames)
|
||||
F8 - Make PCX screen snapshot
|
||||
F9 - Toggle VSync
|
||||
F10 - Toggle speed throttling
|
||||
F11 - Toggle FPS meter
|
||||
|
||||
DOS details:
|
||||
|
||||
You can only support a second player if you are using a joystick driver
|
||||
that supports more than one joystick. (e.g. Sidewinder, dual pads, etc.)
|
||||
|
||||
Type 'gen -help' on the command line for a list of useful options.
|
||||
|
||||
-res <x> <y> set the display resolution.
|
||||
-vdriver <n> specify video driver.
|
||||
-depth <n> specify color depth. (8, 16)
|
||||
-scanlines use scanlines effect.
|
||||
-scale scale display to full resolution. (slow)
|
||||
-vsync wait for vertical sync before blitting.
|
||||
-sound enable sound. (force speed throttling)
|
||||
-sndrate <n> specify sound rate. (8000, 11025, 22050, 44100)
|
||||
-sndcard <n> specify sound card. (0-7)
|
||||
-swap swap left and right stereo output.
|
||||
-joy <s> specify joystick type.
|
||||
|
||||
Here is a list of all the video drivers you can pass as a parameter
|
||||
to the '-vdriver' option:
|
||||
|
||||
auto, safe, vga, modex, vesa2l, vesa3, vbeaf
|
||||
|
||||
Here is a list of all the joystick drivers you can pass as a parameter
|
||||
to the '-joy' option:
|
||||
|
||||
auto, none, standard, 2pads, 4button, 6button, 8button, fspro, wingex,
|
||||
sidewinder, gamepadpro, grip, grip4, sneslpt1, sneslpt2, sneslpt3,
|
||||
psxlpt1, psxlpt2, psxlpt3, n64lpt1, n64lpt2, n64lpt3, db9lpt1, db9lpt2,
|
||||
db9lpt3, tglpt1, tglpt2, tglpt3, wingwar, segaisa, segapci, segapci2
|
||||
|
||||
You can put any commandline option into a plain text file which should
|
||||
be called "gen.cfg". Put one option per line, please. Command line options
|
||||
will override anything in the configuration file.
|
||||
|
||||
Currently the zip loading code can manage a zipfile where the game
|
||||
image is the first thing in it. If you try to open a huge archive of
|
||||
games, only the first will be played.
|
||||
|
||||
Credits and Acknowlegements
|
||||
---------------------------
|
||||
|
||||
I would like to thank Omar Cornut, Christian Schiller, and Chris MacDonald
|
||||
for their invaluable help and support with this project.
|
||||
|
||||
Richard Bannister for the Macintosh port and all of the code fixes and
|
||||
suggestions that have made Genesis Plus a better program.
|
||||
(http://www.bannister.org)
|
||||
|
||||
The Genesis emulator authors: Bart Trzynadlowski, Quintesson, Steve Snake,
|
||||
James Ponder, Stef, Gerrie, Sardu.
|
||||
|
||||
The regular people and many lurkers at segadev.
|
||||
|
||||
The MAME team for the CPU and sound chip emulators.
|
||||
|
||||
Everyone who has contributed, donated, and submitted information to help
|
||||
out Genesis Plus and my efforts documenting the Genesis hardware.
|
||||
|
||||
Contact
|
||||
-------
|
||||
|
||||
Charles MacDonald
|
||||
E-mail: cgfm2@hotmail.com
|
||||
WWW: http://cgfm2.emuviews.com
|
||||
|
||||
Legal
|
||||
-----
|
||||
|
||||
Copyright (C) 1999, 2000, 2001, 2002, 2003 Charles MacDonald
|
||||
|
||||
The source code is distributed under the terms of the GNU General Public
|
||||
License.
|
||||
|
||||
The Z80 CPU emulator, 68K CPU emulator, and the PSG, YM2612 emulation code
|
||||
are taken from the MAME project, and terms of their use are covered under
|
||||
the MAME license.
|
||||
(http://www.mame.net)
|
||||
|
@ -0,0 +1,190 @@
|
||||
|
||||
---------------------------------------
|
||||
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.
|
||||
|
@ -0,0 +1,79 @@
|
||||
|
||||
Here are some technical details about things that need to be fixed or
|
||||
added to Genesis Plus.
|
||||
|
||||
Missing features:
|
||||
|
||||
- Support for 6-button controllers
|
||||
- SRAM management
|
||||
- Game Genie / PAR patch codes
|
||||
|
||||
The VDP code could use a lot of cleaning up.
|
||||
|
||||
The rendering code is missing a few bits:
|
||||
|
||||
- Sprite collision
|
||||
- Window bug
|
||||
|
||||
I think the "C" 68000 emulator either has some bugs or I'm not using it
|
||||
correctly. Older DOS-only versions used Turbo68K, which had ran games
|
||||
much better, especially with regards to interrupt handling.
|
||||
|
||||
Things that need to be fixed:
|
||||
|
||||
- Raster garbage on third road in Thunder Blade.
|
||||
|
||||
- Added country codes for Dragon Slayer, but game locks up after
|
||||
passing country check.
|
||||
|
||||
- No inputs in Samurai Shodown.
|
||||
(This game doesn't initialize the port direction registers, at least not
|
||||
directly. Emulation bug or problem with the game?)
|
||||
|
||||
- Palette and raster problems in Mortal Kombat.
|
||||
|
||||
- Bad raster effects and VRAM corruption in Super Skidmarks.
|
||||
(Needs PAL timing)
|
||||
|
||||
- Palette problems in Sonic 2 title screen.
|
||||
|
||||
- Masked half of Sonic sprite visible on Sonic title screen.
|
||||
|
||||
- Sprite masking doesn't work in Micro Machines subscreen.
|
||||
|
||||
- Music has slow tempo in Batman & Robin. (doesn't seem to be a problem
|
||||
with the YM2612 timers - Wonderboy 3 is normal)
|
||||
|
||||
- Music has jerky playback in Sonic 2, 3, 3D Blast. If you run the Z80
|
||||
emulation for one scanline after requesting an interrupt, it runs fine.
|
||||
|
||||
- DAC and PSG output are too loud, both are divided by two for now
|
||||
(though the PSG should be a bit quieter and the DAC a bit louder)
|
||||
|
||||
- Undead Line locks after selecting a stage, also the Z80 sound halts
|
||||
after the first note is played.
|
||||
|
||||
This game single steps the Z80 with the following code:
|
||||
|
||||
MOVEM.L D0,-(A7) ; 009C7C 48 E7 80 00
|
||||
ORI #$0200,SR ; 009C80 00 7C 02 00
|
||||
; Get control of the Z-bus
|
||||
MOVE.W #$0100,$00A11100 ; 009C84 33 FC 01 00 00 A1 11 00
|
||||
BTST #$00,$00A11100 ; 009C8C 08 39 00 00 00 A1 11 00
|
||||
BNE.S *-$08 [00009C8C] ; 009C94 66 F6
|
||||
; Check driver status byte. If zero, release bus and exit.
|
||||
TST.B $00A00008 ; 009C96 4A 39 00 A0 00 08
|
||||
BEQ *+$0016 [00009CB2] ; 009C9C 67 00 00 14
|
||||
; Release bus and wait for Z80 to resume control. Then restart the loop
|
||||
; and immediately get the bus back again, assuming the Z80 ran at least
|
||||
; one instruction in the meantime.
|
||||
CLR.W $00A11100 ; 009CA0 42 79 00 A1 11 00
|
||||
BTST #$00,$00A11100 ; 009CA6 08 39 00 00 00 A1 11 00
|
||||
BEQ.S *-$08 [00009CA6] ; 009CAE 67 F6
|
||||
BRA.S *-$2C [00009C84] ; 009CB0 60 D2
|
||||
; Release bus and exit.
|
||||
CLR.W $00A11100 ; 009CB2 42 79 00 A1 11 00
|
||||
ANDI #$FDFF,SR ; 009CB8 02 7C FD FF
|
||||
MOVEM.L (A7)+,D0 ; 009CBC 4C DF 00 01
|
||||
RTS ; 009CC0 4E 75
|
||||
|
26
source/docs/ym2612.txt
Normal file
26
source/docs/ym2612.txt
Normal file
@ -0,0 +1,26 @@
|
||||
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.
|
Loading…
Reference in New Issue
Block a user