The SNK NeoGeo always had "mythical"
status during my childhood... everyone knew what one was, but it was
so out of the price-range of what we could hope to get it was never
really on our radar.
The NeoGeo was a simple concept, using the exact same hardware as an
arcade, with just some technical tweaks to make it more suited for
home users... (and unfortunately the same cost!)... the Neo Geo gave
the wealthy the ability to have all the power of high-end arcade
hardware at home..
Now that the NeoGeo is easily emulatable, we can all run - and
develop for - this hardware at home!
Specs:
Neo GEO AES
Cpu
12mhz 68000
Ram
64k
Cart ROM
2MB
Graphics ROM
16MB sprites + 128K Fix Tiles (Font)
Vram
64K + 4K
Resolution
320x224 (288x208 visible) - 4096 colors onscreen
Sprites
380 sprites of size 16x16-16x512 - (96 per line - 380
onscreen)
Bitmap planes
NONE!
Colors
16 per 16x16 sprite - 256 x 16 color palettes from 65536
Sprites
380 sprites onscreen 16 color (16x16 px 32 per line)
(max 96 per line)
Can be chained to make larger sprites
Suport X and Y scaling (Down only)
Sound chip
6mhz Z80 compatible (84C00AM-6) sound CPU
YM2610 + ADPCM
Power
Supply
5V 3A 9V 1.5A (depending on model) Center
pin NEGATIVE
Most Console systems will have 2
types of graphics layer... a 'Tile Map' which is a grid of
predefined 'tiles'... these are usually 8x8 in size... on a 16 bit
system, usually multiple layers of tilemaps exist to define
paralax...
On top of this we would add sprites to make our player character and
other such things...
But the NeoGeo HAS
NO TILEMAP!
So how does the NeoGeo work with no
Tilemap?
Well... sprites on the NeoGeo are 16 pixels wide, and can be up to
512 pixels tall - but they can be combined!... and because the
NeoGeo is capable of a whopping 380 tiles, we can combine 20 of them
together to 'simulate' a tilemap!... this is how background graphics
are drawn on the Neogeo!
On top of this are our 'normal' sprites - enemies, player characters
and such...
There is one final layer, the 'Fix Layer'... this is made up of 16
color 8x8 tiles, in a simple grid... it's designed to do onscreen
text and the like... but I used it in GrimeZ80 to do all the game
graphics... so if your needs are simple, and you want 8x8 block
graphics, it can be used for the job...
but don't worry, we'll learn about sprites later!
The Fix Layer
The Neogeo screen has a resolution of 320x224, and each tile is
8x8 - giving an effective screen size of 40x28...
The actual tilemap is 40x32... the top and bottom two lines are not
show (Shown in red on the chart to the right)
However, because of the CRT layout - it is likely that the left and
rightmost 1 column will not be visible (Shown in orange to the
right)... this gives a visible screen of 38x28
The Fix Layer is positioned in VRAM at &7000 (each position
contains 1 word / 2 bytes)- each Tile is defined by 16 bits in the
following format:
F
E
D
C
B
A
7
8
7
6
5
4
3
2
1
0
P
P
P
P
T
T
T
T
T
T
T
T
T
T
T
T
Where P is the Palette number, and T is the Tile number
The fixmap appears at $7000 in Vram... tile data for the Fixmap are
in ROM
Tiles in memory are ordered in COLUMNS... so in memory (X,Y)
co-ordinate (0,1) comes after (0,0) ($7000)... and (1,0) comes 32
words ($7020) after (0,0)
For example - to set tile (0,2) to tile 256 in palette 1 (note this
is in the "May be offscreen" area, but should appear on an emulator)
Move.W #$7002,d1
;Address - Tile 2
Move.W #$1100,d0
;PTTT -
Palette and tile
Move.w d1,$3C0000 ;set address in vdp
Move.w d0,$3C0002
;set tile data in vdp
Fix Layer tiles are in an odd format!
Each tile is 8x8 at 4bpp ... so 32 bytes per tile...
The two nibbles of each byte represent 2 pixels , but they are
BACKWARDS... so the 1st (High) nibble is the 2nd pixel color, and
the 2nd nibble (Low) is the 1st pixel color
The bytes are stored in Columns, then rows... and the columns are
out of order too! .. Visible pixels ABCDEFGH are stored in Ram in
order FEHGBADC
The 8 bytes of each column are in normal top->bottom format... so
at least that:s something!
My AkuSprite editor (used in these tutorials) has support to
export images in the correct "Fix" format for the NeoGeo
Vram Map
Each address contains a WORD...
Write a word to $3C0000 to select VRAM Address
Write a word to $3C0002 to Send data to VRAM
Start
End
Words
Zone
Description
$0000
$6FFF
28672
Lower
SpriteData
1 � Tile/Palette
$7000
$74FF
4096
Fix
map
$7500
$7FFF
Extension
$8000
$81FF
512
Upper
SpriteData
2 - Scale
$8200
$83FF
512
SpriteData
3 � Ypos
$8400
$85FF
512
SpriteData
4 � Xpos
$8600
$867F
128
Sprite
list for even scanlines
$8680
$86FF
128
Sprite
list for odd scanlines
$8700
$87FF
256
Unused
(free)
MAME NeoGeo Rom XMLs
To run a custom game on MAME, we need to create a hash file -
usually called 'neogeo.xml'
This defines how the various binary files that make up a game are
attached to the system... multiple files can be combined for a
single purpose - the 'Offset'
Section NAME
Detail
How to make this?
maincpu
68000 binary data
compile a 68000 ASM file with VASM
fixed
FIX Layer Tiles
My AkuSprite Editor can make this format
audiocpu
Z80 binary data
compile a z80 ASM file with VASM
sprites
Sprite pattern data
My AkuSprite Editor can make this format
There are various parameters for 'rom'
files that must correct for MAME to be happy, otherwise you will get
the error "One or more ROMs/CHDs for this machine are incorrect. The
machine may not run correctly"...
To fix this you must ensure the following parameters are correct:
parameter
name
Detail
code used by my
MakeNeoGeoHash.exe
size
File size in bytes (0x denotes it's in HEX)
%size%
crc
Cyclic Redundancy Check (32 bit) of file
%crc%
sha1
sha1 of file
%sha%
If you want to calculate the hashes, you can do so with my 'MakeNeoGeoHash'
program - you need to provide it a template (shown to the right) -
it will calculate the size,crc and sha1 of each rom, and write out a
new xml which mame will be happy with!
MakeNeoGeoHash is included in my 68000 development tools package,
with scripts to use it automatically with my tutorials samples
Memory Map
Function
Port
Details
$000000
Vector
Table
$000100
Cart
Header
and User Vectors
$000400
1st
bank
of Rom
$100000
Ram
(64k)
BIOS_SYSTEM_MODE
$10FD80
(byte)
VBL
for $00=system,$80=game
BIOS_SYSRET_STATUS
$10FD81
(byte)
Stores
function code for SYSTEM_RETURN
BIOS_MVS_FLAG
$10FD82
(byte)
0=Home/AES,1=MVS
BIOS_COUNTRY_CODE
$10FD83
(byte)
0=Japan,1=USA,2=Europe/Export
(xxx:Korea?)
BIOS_GAME_DIP
$10FD84
$10FD84-$10FD93
(all
bytes)
BIOS_GAMEDIP_TIME1
$10FD84
(word)
timed
option 1 (minutes and seconds in BCD)
BIOS_GAMEDIP_TIME2
$10FD86
(word)
timed
option 2 (minutes and seconds in BCD)
BIOS_GAMEDIP_COUNT1
$10FD88
(byte)
counter
option 1 (1-99; value set here is default)
(byte)
Start
and Select from current frame (Select bits = 0 on MVS)
BIOS_STATCHANGE
$10FDAD
(byte)
Start
and Select active-edge input (Select bits = 0 on MVS)
BIOS_USER_REQUEST
$10FDAE
(byte)
Command
for USER ($122)
BIOS_USER_MODE
$10FDAF
(byte)
Current
game status (0:init/boot, 1:title/demo, 2:game)
BIOS_CREDIT1_DEC
$10FDB0
(byte)
Credit
decrement Player 1 (BCD)
BIOS_CREDIT2_DEC
$10FDB1
(byte)
Credit
decrement Player 2 (BCD)
BIOS_CREDIT3_DEC
$10FDB2
(byte)
Credit
decrement Player 3 (BCD)
BIOS_CREDIT4_DEC
$10FDB3
(byte)
Credit
decrement Player 4 (BCD)
BIOS_START_FLAG
$10FDB4
(byte)
Player(s)
starting the game on PLAYER_START call
BIOS_PLAYER1_MODE
$10FDB6
(byte)
Player
1 Status (a.k.a. "BIOS_PLAYER_MOD1")
BIOS_PLAYER2_MODE
$10FDB7
(byte)
Player
2 Status
BIOS_PLAYER3_MODE
$10FDB8
(byte)
Player
3 Status
BIOS_PLAYER4_MODE
$10FDB9
(byte)
Player
4 Status
;???
$10FDBA
(long)
BIOS_MESS_POINT
$10FDBE
(long)
pointer
to MESS_OUT buffer
BIOS_MESS_BUSY
$10FDC2
(word)
0=run
MESS_OUT, 1=skip MESS_OUT
BIOS_CARD_COMMAND
$10FDC4
(byte)
Command
to execute
BIOS_CARD_MODE
$10FDC5
(byte)
"command
error job mode"
BIOS_CARD_ANSWER
$10FDC6
(byte)
answer
code for command; set by BIOS
;BIOS_??????????
$10FDC7
(byte)
?
BIOS_CARD_START
$10FDC8
(long)
Pointer
to start of card data
BIOS_CARD_SIZE
$10FDCC
(word)
Size
of data
BIOS_CARD_FCB
$10FDCE
(word)
Game
NGH number
BIOS_CARD_SUB
$10FDD0
(byte/word)
Game
sub number (0-15)
BIOS_DATE_TIME
$10FDD2
DATE_TIME
struct
BIOS_YEAR
$10FDD2
(byte)
Current
Year (starts at ??)
BIOS_MONTH
$10FDD3
(byte)
Current
Month
BIOS_DAY
$10FDD4
(byte)
Current
Day
BIOS_WEEKDAY
$10FDD5
(byte)
Current
Weekday (0:Sunday, 1:Monday, ... 6:Saturday)
BIOS_HOUR
$10FDD6
(byte)
Current
Hour (24 hour format)
BIOS_MINUTE
$10FDD7
(byte)
Current
Minute
BIOS_SECOND
$10FDD8
(byte)
Current
Second
;BIOS_??????????
$10FDD9
(byte)
?
BIOS_SELECT_TIMER
$10FDDA
(word)
(a.k.a.
"compulsion timer")
BIOS_START_TEST
$10FDDC
(word)
??
(might be used differently on CD systems)
BIOS_COIN_LEVER
$10FDDE
(word)
??
BIOS_WORK1
$10FE00
BIOS_CREDIT1
$10FE00
(byte)
BIOS_CREDIT2
$10FE01
(byte)
BIOS_CREDIT3
$10FE02
(byte)
BIOS_CREDIT4
$10FE03
(byte)
BIOS_SWITCH_STORE
$10FE04
(long)
BIOS_UNDER_CREDIT1
$10FE08
(byte)
BIOS_UNDER_CREDIT2
$10FE09
(byte)
BIOS_UNDER_CREDIT3
$10FE0A
(byte)
BIOS_UNDER_CREDIT4
$10FE0B
(byte)
BIOS_UNDER_CREDIT5
$10FE0C
(byte)
BIOS_UNDER_CREDIT6
$10FE0D
(byte)
BIOS_UNDER_CREDIT7
$10FE0E
(byte)
BIOS_UNDER_CREDIT8
$10FE0F
(byte)
BIOS_COIN1_NOR_CRED
$10FE10
(word)
BIOS_COIN2_NOR_CRED
$10FE12
(word)
BIOS_COIN1_CONT_CRED
$10FE14
(word)
BIOS_COIN2_CONT_CRED
$10FE16
(word)
BIOS_SELECT_FREE
$10FE18
(byte)
;???
$10FE19
(byte)
BIOS_NON_LIMIT
$10FE1A
(byte/word?)
BIOS_DEMO_SOUND
$10FE1C
(byte)
BIOS_INIT_MARK
$10FE1E
(word)
BIOS_SR_STORE
$10FE20
(word)
BIOS_VERSION_BASE
$10FE22
(long)
BIOS_GD_STORE
$10FE26
(byte)
32
bytes
BIOS_WORK2
$10FE80
BIOS_DEVMODE
$10FE80
(byte)
nonzero
value = enabled
BIOS_FRAMECOUNT
$10FE88
(long)
(a.k.a.
"SYS_INT1_TIMER")
BIOS_SYS_STOPPER
$10FE8C
(byte)
"system
stopper", actually BIOS VBlank flag
BIOS_Z80_BANK
$10FE8D
(byte)
BIOS_SYSTEM_MODE2
$10FE8E
(word)
BIOS_CARD_TIMER
$10FE90
(word)
BIOS_CARD_START2
$10FE92
(long)
BIOS_CARD_SIZE2
$10FE96
(word)
BIOS_CARD_FCB2
$10FE98
(word)
BIOS_CARD_SUB2
$10FE9A
(word)
BIOS_DIR_BUFFER
$10FE9C
(byte)
20
bytes
BIOS_DIR_NUMBER
$10FEB0
(word)
5
words
BIOS_FIX_STORE_FLAG
$10FEBA
(byte)
BIOS_LED_OFF
$10FEBB
(byte)
BIOS_IN_TEST
$10FEBC
(byte)
BIOS_INST_MODE
$10FEBD
(byte)
BIOS_START_BUSY
$10FEBE
(byte)
BIOS_BACKUP_MODE
$10FEBF
(byte)
(a.k.a.
"BIOS_BRAM_USED")
BIOS_INST_RAD
$10FEC0
(long)
BIOS_INST_RCO
$10FEC4
(byte)
BIOS_TITLE_MODE
$10FEC5
(byte)
When
set to 1, stops BIOS from calling command 3 twice after Game Over
if credits are in the system. -paraphrasing Razoola, NeoGeo
Development Wiki
BIOS_MESS_STACK
$10FEC6
(long)
5
longs; first is the pointer to the data.
BIOS_STATCURNT_RAW
$10FEDC
(byte)
raw
version of BIOS_STATCURNT (includes Select on MVS) (a.k.a.
"INPUT_SS")
BIOS_STATCHANGE_RAW
$10FEDD
(byte)
raw
version of BIOS_STATCHANGE (includes Select on MVS)
Stop
timer for 32 lines in PAL mode? (LSPC2 only, apparently)
PALETTES
$400000
$400000-$401FFF
(2 bytes per color - 16 colors - 256 palettes)
PALETTE_REFERENCE
$400000
Reference
Color (must be $8000)
PALETTE_BACKDROP
$401FFE
Backdrop
Color
MEMCARD_DATA
$800000
Memory
Card Data (a.k.a. "IC_MEMORY")
BIOSROM
$C00000
BIOS
ROM begins at $C00000
SYSTEM_RESET
$C00402
SYSTEM_INT1
$C00438
System
VBlank
SYSTEM_INT2
$C0043E
System
Int2 (Cart systems only)
SYSTEM_RETURN
$C00444
Returns
from the game to the BIOS
SYSTEM_IO
$C0044A
Reads
player inputs (and cabinet if MVS)
CREDIT_CHECK
$C00450
Check
a player's number of credits
CREDIT_DOWN
$C00456
Deduct
credits
READ_CALENDAR
$C0045C
Read
values from uPD4990 chip (MVS-only)
SETUP_CALENDAR
$C00462
Sets
up uPD4990 chip (MVS-only)
SYS_CARD
$C00468
Memory
Card commands
SYS_CARD_ERROR
$C0046E
Handle
card errors and display message
SYSTEM_HOW_TO_PLAY
$C00474
display
old-style how to play. uncomment if you want to use it.
CALC_CHECKSUM
$C0047A
calc
a checksum and loop forever
FIX_CLEAR
$C004C2
Clear
Fix layer
LSP_1st
$C004C8
Clear
SCB2-4, first SCB1 tilemap
MESS_OUT
$C004CE
Fix
layer message output
CONTROLLER_SETUP
$C004D4
Initializes
controllers
BIOSF_HBLANK
$C004DA
HBlank
handler (replaces SYSTEM_INT2)
BIOSF_UPLOAD
$C00546
Upload
data to DRAM
$C0054C
?
(CDZ)
BIOSF_LOADFILE
$C00552
Load
file from CD, with animation
$C00558
?
(CDZ)
BIOSF_CDPLAYER
$C0055E
Reset
to CD Player
BIOSF_LOADFILEX
$C00564
Load
file from CD, no animation
BIOSF_CDDACMD
$C0056A
Issue
CDDA command
BIOSF_VIDEOEN
$C00570
Enable/Disable
video layers
UPLOAD
$E00000
CD
Upload
Zone ($E00000-$EFFFFF)
$F00000
Registers
Color definitions
Palette data is stored between $400000-$401FFF
Each color is 2 bytes in size, there are 16 colors in each palette, and 256
palettes.
The first color in the first palette is special ($400000), it must be
$8000... this is called the "Reference color"
The last color in the last palette is special ($401FFE), it is the
"Background" color that shows through, when all other layers are transparent
the 16 bits of Color data are in the following format:
F
E
D
C
B
A
9
8
7
6
5
4
3
2
1
0
D
R0
G0
B0
R4
R3
R2
R1
G4
G3
G2
G1
B4
B3
B2
B1
The Color format is quite odd!
each color is defined by 5 bits.. .but the lowest bits for each channel is
separate from the rest... this means each color can be quickly defined by a
single nibble - or all 5 can be used together...
There is also a "Dark" bit... which is effectively the least significant bit
for all 3 color channels.
FM Sound with the YM2610
Get the YM2610 PDF
for all the info!
The FM chip uses 2 pairs of ports, $04 and $06 select the address of the
register we want to change, $05 and $07 write the new data, but after each
write, we need to check if the FM chip is busy,
To check if the FM chip is busy, read in from port $04, and check bit 7 -
it will return 0 when not busy.
Address
Function
Port
$04 / $05
Port
$06 / $07
Bits
Details
$21
LSI Test Data
ALL
TTTTTTTT
T=Test
$22
LFO Frequency
Control
ALL
----EFFF
E=enable
F=Frequency
$24
Timer A H
ALL
HHHHHHHH
Timer A top 8
bits
$25
Timer A L
ALL
------LL
Timer A
bottom 2 bits
$26
Timer B
ALL
TTTTTTTT
T=Timer B
$27
Timer
Control, 2ch mode
ALL
MMRREELL
M=Multi Mode,
R=Reset timers, E=enable, L=Load
$28
Individual
Operator Key On/Off
ALL
-
OOOO-GCC
O=operator /
G=Channel group / C=Channel (0=chn 1)
$31
Multiplier
& Detune
Ch1 Op1
Ch3 Op1
-DDDMMMM
D=Detune /
M=Multiplier
$32
Multiplier
& Detune
Ch2 Op1
Ch4 Op1
-DDDMMMM
D=Detune /
M=Multiplier
$35
Multiplier
& Detune
Ch1 Op2
Ch3 Op2
-DDDMMMM
D=Detune /
M=Multiplier
$36
Multiplier
& Detune
Ch2 Op2
Ch4 Op2
-DDDMMMM
D=Detune /
M=Multiplier
$39
Multiplier
& Detune
Ch1 Op3
Ch3 Op3
-DDDMMMM
D=Detune /
M=Multiplier
$3A
Multiplier
& Detune
Ch2 Op3
Ch4 Op3
-DDDMMMM
D=Detune /
M=Multiplier
$3D
Multiplier
& Detune
Ch1 Op4
Ch3 Op4
-DDDMMMM
D=Detune /
M=Multiplier
$3E
Multiplier
& Detune
Ch2 Op4
Ch4 Op4
-DDDMMMM
D=Detune /
M=Multiplier
$41
Total Level
Ch1 Op1
Ch3 Op1
-TTTTTTT
T=Total Level
(0=max)
$42
Total Level
Ch2 Op1
Ch4 Op1
-TTTTTTT
T=Total Level
(0=max)
$45
Total Level
Ch1 Op2
Ch3 Op2
-TTTTTTT
T=Total Level
(0=max)
$46
Total Level
Ch2 Op2
Ch4 Op2
-TTTTTTT
T=Total Level
(0=max)
$49
Total Level
Ch1 Op3
Ch3 Op3
-TTTTTTT
T=Total Level
(0=max)
$4A
Total Level
Ch2 Op3
Ch4 Op3
-TTTTTTT
T=Total Level
(0=max)
$4D
Total Level
Ch1 Op4
Ch3 Op4
-TTTTTTT
T=Total Level
(0=max)
$4E
Total Level
Ch2 Op4
Ch4 Op4
-TTTTTTT
T=Total Level
(0=max)
$51
Key Scaling
& Attack Rate
Ch1 Op1
Ch3 Op1
KK-RRRRR
K=Keyscaling
/ R=attackrate
$52
Key Scaling
& Attack Rate
Ch2 Op1
Ch4 Op1
KK-RRRRR
K=Keyscaling
/ R=attackrate
$55
Key Scaling
& Attack Rate
Ch1 Op2
Ch3 Op2
KK-RRRRR
K=Keyscaling
/ R=attackrate
$56
Key Scaling
& Attack Rate
Ch2 Op2
Ch4 Op2
KK-RRRRR
K=Keyscaling
/ R=attackrate
$59
Key Scaling
& Attack Rate
Ch1 Op3
Ch3 Op3
KK-RRRRR
K=Keyscaling
/ R=attackrate
$5A
Key Scaling
& Attack Rate
Ch2 Op3
Ch4 Op3
KK-RRRRR
K=Keyscaling
/ R=attackrate
$5D
Key Scaling
& Attack Rate
Ch1 Op4
Ch3 Op4
KK-RRRRR
K=Keyscaling
/ R=attackrate
$5E
Key Scaling
& Attack Rate
Ch2 Op4
Ch4 Op4
KK-RRRRR
K=Keyscaling
/ R=attackrate
$61
Decay Rate
& AM Enable
Ch1 Op1
Ch3 Op1
A--DDDDD
A=Amplitude
Mod Enable / D= Decay rate
$62
Decay Rate
& AM Enable
Ch2 Op1
Ch4 Op1
A--DDDDD
A=Amplitude
Mod Enable / D= Decay rate
$65
Decay Rate
& AM Enable
Ch1 Op2
Ch3 Op2
A--DDDDD
A=Amplitude
Mod Enable / D= Decay rate
$66
Decay Rate
& AM Enable
Ch2 Op2
Ch4 Op2
A--DDDDD
A=Amplitude
Mod Enable / D= Decay rate
$69
Decay Rate
& AM Enable
Ch1 Op3
Ch3 Op3
A--DDDDD
A=Amplitude
Mod Enable / D= Decay rate
$6A
Decay Rate
& AM Enable
Ch2 Op3
Ch4 Op3
A--DDDDD
A=Amplitude
Mod Enable / D= Decay rate
$6D
Decay Rate
& AM Enable
Ch1 Op4
Ch3 Op4
A--DDDDD
A=Amplitude
Mod Enable / D= Decay rate
$6E
Decay Rate
& AM Enable
Ch2 Op4
Ch4 Op4
A--DDDDD
A=Amplitude
Mod Enable / D= Decay rate
$71
Sustain Rate
Ch1 Op1
Ch3 Op1
---SSSSS
S=Sustain
Rate
$72
Sustain Rate
Ch2 Op1
Ch4 Op1
---SSSSS
S=Sustain
Rate
$75
Sustain Rate
Ch1 Op2
Ch3 Op2
---SSSSS
S=Sustain
Rate
$76
Sustain Rate
Ch2 Op2
Ch4 Op2
---SSSSS
S=Sustain
Rate
$79
Sustain Rate
Ch1 Op3
Ch3 Op3
---SSSSS
S=Sustain
Rate
$7A
Sustain Rate
Ch2 Op3
Ch4 Op3
---SSSSS
S=Sustain
Rate
$7D
Sustain Rate
Ch1 Op4
Ch3 Op4
---SSSSS
S=Sustain
Rate
$7E
Sustain Rate
Ch2 Op4
Ch4 Op4
---SSSSS
S=Sustain
Rate
$81
Release Rate
& Sustain Level
Ch1 Op1
Ch3 Op1
SSSSRRRR
S=Sustain
Level / Release Rate
$82
Release Rate
& Sustain Level
Ch2 Op1
Ch4 Op1
SSSSRRRR
S=Sustain
Level / Release Rate
$85
Release Rate
& Sustain Level
Ch1 Op2
Ch3 Op2
SSSSRRRR
S=Sustain
Level / Release Rate
$86
Release Rate
& Sustain Level
Ch2 Op2
Ch4 Op2
SSSSRRRR
S=Sustain
Level / Release Rate
$89
Release Rate
& Sustain Level
Ch1 Op3
Ch3 Op3
SSSSRRRR
S=Sustain
Level / Release Rate
$8A
Release Rate
& Sustain Level
Ch2 Op3
Ch4 Op3
SSSSRRRR
S=Sustain
Level / Release Rate
$8D
Release Rate
& Sustain Level
Ch1 Op4
Ch3 Op4
SSSSRRRR
S=Sustain
Level / Release Rate
$8E
Release Rate
& Sustain Level
Ch2 Op4
Ch4 Op4
SSSSRRRR
S=Sustain
Level / Release Rate
$91
SSG-Envelope
Generator
Ch1 Op1
Ch3 Op1
----EEEE
E=Envelope
Gen
$92
SSG-Envelope
Generator
Ch2 Op1
Ch4 Op1
----EEEE
E=Envelope
Gen
$95
SSG-Envelope
Generator
Ch1 Op2
Ch3 Op2
----EEEE
E=Envelope
Gen
$96
SSG-Envelope
Generator
Ch2 Op2
Ch4 Op2
----EEEE
E=Envelope
Gen
$99
SSG-Envelope
Generator
Ch1 Op3
Ch3 Op3
----EEEE
E=Envelope
Gen
$9A
SSG-Envelope
Generator
Ch2 Op3
Ch4 Op3
----EEEE
E=Envelope
Gen
$9D
SSG-Envelope
Generator
Ch1 Op4
Ch3 Op4
----EEEE
E=Envelope
Gen
$9E
SSG-Envelope
Generator
Ch2 Op4
Ch4 Op4
----EEEE
E=Envelope
Gen
$A1
Frequency low
(Write Second)
Ch1
Ch3
PPPPPPPP
P=Frequency
Position L
$A2
Frequency low
(Write Second)
Ch2
Ch4
PPPPPPPP
P=Frequency
Position L
$A5
Frequency
high & Octave (Write first)
Ch1
Ch3
--OOOPPP
O=Octive /
P=Position H
$A6
Frequency
high & Octave (Write first)
Ch2
Ch4
--OOOPPP
O=Octive /
P=Position H
$A9
Frequency low
during Multi-Mode
Ch1
Ch3
PPPPPPPP
P=Frequency
Position L
$AA
Frequency low
during Multi-Mode
Ch2
Ch4
PPPPPPPP
P=Frequency
Position L
$AD
Frequency
high & Octave during Multi-Mode
Ch1
Ch3
--OOOPPP
O=Octive /
P=Position H
$AE
Frequency
high & Octave during Multi-Mode
Ch2
Ch4
--OOOPPP
O=Octive /
P=Position H
$B1
Algorithm
& Feedback
Ch1
Ch3
--FFFAAA
F=Feedback /
A=Algorithm
$B2
Algorithm
& Feedback
Ch2
Ch4
--FFFAAA
F=Feedback /
A=Algorithm
$B5
FMS & AMS
& Stereo
Ch1
Ch3
LRAA-FFF
Left / Right
(1=on) / A=Amplitude Mod Sensitivity / F=Frequency Mod Sensitivity
$B6
FMS & AMS
& Stereo
Ch2
Ch4
LRAA-FFF
Left / Right
(1=on) / A=Amplitude Mod Sensitivity / F=Frequency Mod Sensitivity
The NeoGeo sound
chip is backwards compatible with the AY... and cannot be accessed
by the 68000, so we have to get the Z80 CPU to do the sound
work...
The Z80 has its own program code contained in a ROM and separate
memory - and we have to pass data betrween the Z80 and 68000 with
a single byte RW port!
Writes to Z80 port &0C can be read from 68000 port
$320000 , and writes to 68000 port $32000 can be read from
port &00
Sound Ports
Communication between the Z80 and 68000 work with the following ports
Z80
68000
Read
Port &00
Address $320000
Write
Port &0C
Address $320000
FM Algorithm (&B1/B2)
The algorithm number is one of 8 - each one defines how the different
operations build up to build a sound:
FM Sound over time
The sound created is affected over time by the various registers, we can
see a simple representation below:
Z80 Sound Commands
The Z80 can recieve single byte commands from the 68000 to the
Z80, it can also return a single byte
Command
Meaning
$00
nop/do nothing
$01
Slot switch (needed by bios)
$02
Play eyecatch music (needed by bios)
$03
Soft Reset (needed by bios)
$04
Disable All (Music & Sounds)
$05
Disable Music
$06
Disable Sounds
$07
Enable All (Music & Sounds)
$08
Enable Music
$09
Enable Sounds
$0A
Silence SSG channels
$0B
Silence FM channels
$0C
Stop all ADPCM-A samples
$0D
Stop current ADPCM-B sample
$0E
Tempo Change (1 argument; new tempo)
$0F
unused
$10
Fade Out (1 argument; fade speed)
$11
Stop Fade In/Out
$12
Fade In (1 argument; fade speed)
$13-$1F
Unused
$20-FF
Free for user use
The YM1610 is backwards compatible with the AY-3-8910 - we covered using
this chip in the Z80
Tutorials here!
Hardware Sprites
On the NeoGeo Sprites are 16 pixels
wide, and are made up of tiles 16 pixels tall... they are 16 colors
(4 bitplanes) so each tile is 128 bytes... The NeoGeo is capable of
up to 380 sprites total.
A sprite can be made up of up to 32 tiles to make the sprite
taller... there is also a 'Chain' bit - this will connect a sprite
to the previous sprite (Sharing its position) to make a sprite
wider!
Hardware sprite Tiles are not in the same format as the FIX layer -
they are 16x16 pixels in size and use bitplanes, but the layout is
odd, and they are split onto two rom files (C1/C2 or C3/C4 etc)
The sprite is split into 2x 8 pixel wide 'columns' the rightmost one
is stored first - each pair of bitplanes 0 & 1 are stored
together in ROM C1 - and 2 & 3 are stores in ROM C2 - all 16
lines of the right half are stored first - then the 16 lines of the
left side are stored - making a total of 128 bytes (64 in each file)
Sprite Attributes
Each sprite is defined by 1-32 tile definitions, A palette/flip byte, a
Scale byte, a Ypos/Height byte and an Xpos... lets see what all these bits
do in detail!
Note, it's possible to scale a sprite DOWN, but it's not possible to scale
them up...
Address of
Bit
Function
Sprite 1
F
E
D
C
B
A
9
8
7
6
5
4
3
2
1
0
Purpose
Sample
TileAddr 1,2..32
$0040,$0042�$007E
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N
N=Tile Number L
$2000
TilePal 1,2..32
$0041,$0043...$007F
P
P
P
P
P
P
P
P
N
N
N
N
A
A
V
H
P=Pallete, N=tile
Number H, A=Animate (4/8) V=Vflip H=Hflip
$0100
Shrink
$8001
-
-
-
-
H
H
H
H
V
V
V
V
V
V
V
V
H=H shrink (F=off), V=V
shrink (FF=off)
$0FFF
Ypos
$8201
Y
Y
Y
Y
Y
Y
Y
Y
Y
C
T
T
T
T
T
T
Y=Y pos (from bottom,
so 288+208-Y) C=Chain another sprite on right, T=Tile count
vertically
$E002
Xpos
$8401
X
X
X
X
X
X
X
X
X
-
-
-
-
-
-
-
X=X pos (from left)
$0800
Valid Tile Counts (T) are 1-12 , 32 and 33 (13-31 are invalid)
A special Tile Height of 33 makes the sprite the Full height of screen -
use for building a 'tilemap'
Note: Tile number $2000 would be loaded at ROM address 0x100000 in the
XML
Sprite Attribute Addresses
We need to set various addresses in the Sprite Attribute data... to do this
we use two 68000 addresses...
First we write the Address of the Sprite Attribute we want to change to $3C0000, then we write the new word value for the
address to $3C0002
If you want to AutoInc the VRAM destination after each write, write 1 to
$3C0004 or 0 to turn it off.
Sprite
Num
TileAddr
(1st)
TilePal
(1st)
TileAddr
(32nd)
TilePal
(32nd)
Shrink
Ypos
Xpos
0
$0000
$0001
$003E
$003F
$8000
$8200
$8400
1
$0040
$0041
$007E
$007F
$8001
$8201
$8401
2
$0080
$0081
$00BE
$00BF
$8002
$8202
$8402
3
$00C0
$00C1
$00FE
$00FF
$8003
$8203
$8403
�
�
�
�
�
�
�
�
379
$5EC0
$5EC1
$5EC0
$5EC1
$817B
$837B
$857B
To the right is the source of a
working example for showing a 32x32 sprite! (made up of 2 chained
sprites of 2 tiles each)
In MAME We need to load our sprites into the $10000 area for this to
work - a working XML is shown below:
Note... Mame will sulk (immediately close) unless
the file size of all these sprites are exactly 1MB each (1,048,576
bytes)
;$3C0000=Select
VRAM Address ;$3C0002=Send data to VRAM
move.w #$0040,$3C0000
;Show Tile 0 from bank
$100000
move.w #$2000,$3C0002
;NNNNNNNN Tile - my tiles
start at $2000
move.w #$8400+2,$3C0000
;Xpos ignored due to Chain
move.w #$0000,$3C0002 ;XXXXXXXX X------- Xpos
If you're shrinking sprites, and it's causing
'glitches' in the transparent areas of the sprite (black animated
dots) try setting the other tiles of the sprite to a transparent
pattern (even if they shouldn't be used) - It seems to fix the
issue!