68000 Assembly Programming for
the NeoGeo
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 |
|
|
ChibiAkumas Tutorials
Screen layers...Where's
my Tilemap!
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) |
BIOS_GAMEDIP_COUNT2 |
$10FD89 |
(byte)
counter
option 2 (WITHOUT, INFINITE, 1-99 TIMES) |
BIOS_GAMEDIP_01 |
$10FD8A |
(byte)
Game
soft dip 01 |
BIOS_GAMEDIP_02 |
$10FD8B |
(byte)
Game
soft dip 02 |
BIOS_GAMEDIP_03 |
$10FD8C |
(byte)
Game
soft dip 03 |
BIOS_GAMEDIP_04 |
$10FD8D |
(byte)
Game
soft dip 04 |
BIOS_GAMEDIP_05 |
$10FD8E |
(byte)
Game
soft dip 05 |
BIOS_GAMEDIP_06 |
$10FD8F |
(byte)
Game
soft dip 06 |
BIOS_GAMEDIP_07 |
$10FD90 |
(byte)
Game
soft dip 07 |
BIOS_GAMEDIP_08 |
$10FD91 |
(byte)
Game
soft dip 08 |
BIOS_GAMEDIP_09 |
$10FD92 |
(byte)
Game
soft dip 09 |
BIOS_GAMEDIP_10 |
$10FD93 |
(byte)
Game
soft dip 10 |
BIOS_P1STATUS |
$10FD94 |
(byte)
Controller
1 status |
BIOS_P1PREVIOUS |
$10FD95 |
(byte)
Inputs
from last frame |
BIOS_P1CURRENT |
$10FD96 |
(byte)
Inputs
from current frame |
BIOS_P1CHANGE |
$10FD97 |
(byte)
Active-edge
input |
BIOS_P1REPEAT |
$10FD98 |
(byte)
Auto-repeat
flag |
BIOS_P1TIMER |
$10FD99 |
(byte)
Input
repeat timer |
BIOS_P2STATUS |
$10FD9A |
(byte)
Controller
2 status |
BIOS_P2PREVIOUS |
$10FD9B |
(byte)
Inputs
from last frame |
BIOS_P2CURRENT |
$10FD9C |
(byte)
Inputs
from current frame |
BIOS_P2CHANGE |
$10FD9D |
(byte)
Active-edge
input |
BIOS_P2REPEAT |
$10FD9E |
(byte)
Auto-repeat
flag |
BIOS_P2TIMER |
$10FD9F |
(byte)
Input
repeat timer |
BIOS_P3STATUS |
$10FDA0 |
(byte)
Controller
3 status |
BIOS_P3PREVIOUS |
$10FDA1 |
(byte)
Inputs
from last frame |
BIOS_P3CURRENT |
$10FDA2 |
(byte)
Inputs
from current frame |
BIOS_P3CHANGE |
$10FDA3 |
(byte)
Active-edge
input |
BIOS_P3REPEAT |
$10FDA4 |
(byte)
Auto-repeat
flag |
BIOS_P3TIMER |
$10FDA5 |
(byte)
Input
repeat timer |
BIOS_P4STATUS |
$10FDA6 |
(byte)
Controller
4 status |
BIOS_P4PREVIOUS |
$10FDA7 |
(byte)
Inputs
from last frame |
BIOS_P4CURRENT |
$10FDA8 |
(byte)
Inputs
from current frame |
BIOS_P4CHANGE |
$10FDA9 |
(byte)
Active-edge
input |
BIOS_P4REPEAT |
$10FDAA |
(byte)
Auto-repeat
flag |
BIOS_P4TIMER |
$10FDAB |
(byte)
Input
repeat timer |
BIOS_STATCURNT |
$10FDAC |
(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) |
BIOS_INPUT_TT1 |
$10FEDE |
(byte) |
BIOS_INPUT_TT2 |
$10FEDF |
(byte) |
BIOS_KYOUSEI_MODE |
$10FEE0 |
(byte)
a.k.a.
"KYOUSEI_MODE" (Game start compulsion?) |
BIOS_SYS_STOP |
$10FEE1 |
(byte)
(a.k.a.
"BIOS_FRAME_SKIP","SYS_STOP") |
BIOS_CS_REMAIN |
$10FEE2 |
(byte)
(a.k.a.
"CS_REMAIN") |
BIOS_INT_OFF |
$10FEE3 |
(byte)
(a.k.a.
"BIOS_INT1_SKIP", "INT_OFF") |
BIOS_INT1_TIMER2 |
$10FEE4 |
(word?)
(a.k.a.
"BIOS_INT1_FRAME_COUNTER", "INT1_TIMER2") |
BIOS_P5STATUS |
$10FEE8 |
(byte)
Input
5 status |
BIOS_P5PREVIOUS |
$10FEE9 |
(byte)
Inputs
from last frame |
BIOS_P5CURRENT |
$10FEEA |
(byte)
Inputs
from current frame |
BIOS_P5CHANGE |
$10FEEB |
(byte)
Active-edge
input |
BIOS_P5REPEAT |
$10FEEC |
(byte)
Auto-repeat
flag |
BIOS_P5TIMER |
$10FEED |
(byte)
Input
repeat timer |
BIOS_P6STATUS |
$10FEEE |
(byte)
Input
6 status |
BIOS_P6PREVIOUS |
$10FEEF |
(byte)
Inputs
from last frame |
BIOS_P6CURRENT |
$10FEF0 |
(byte)
Inputs
from current frame |
BIOS_P6CHANGE |
$10FEF1 |
(byte)
Active-edge
input |
BIOS_P6REPEAT |
$10FEF2 |
(byte)
Auto-repeat
flag |
BIOS_P6TIMER |
$10FEF3 |
(byte)
Input
repeat timer |
BIOS_MESS_BUFFER |
$10FF00 |
100
byte
buffer |
BIOS_4P_REQUESTED |
$10FEF8 |
(bios)
local
copy of hard dip 2 (0=off; 2=on) |
BIOS_4P_MODE |
$10FEFA |
(bios)
Main
4P flag (0=regular; $FF=4P ok) |
BIOS_4P_PLUGGED |
$10FEFB |
(bios)
Is
NEO-FTC1B board present? (0=not found; $FF=plugged in) |
BIOS_CD_UPZONE |
$10FEDA |
(byte)
zone
(0=PRG/TXT, 1=FIX, 2=SPR, 3=Z80, 4=PCM, 5=PAT, 6=???, 7=OBJ,
8=A**) |
BIOS_CD_UPBANK |
$10FEDB |
(byte)
bank |
BIOS_CD_UPDEST |
$10FEF4 |
(long)
destination
address |
BIOS_CD_UPSRC
|
$10FEF8 |
(long)
source
address |
BIOS_CD_UPSIZE |
$10FEFC |
(long)
size |
|
$110000 |
Ram
Mirror |
|
$200000 |
2nd
bank
of Rom |
REG_P1CNT |
$300000
|
Player
1 Controls (DCBArldu)/Trackball data [active low] |
REG_DIPSW |
$300001
|
Read
Hardware DIPs [active low], Kick watchdog (a.k.a. "WATCH_DOG") |
REG_SOUND |
$320000
|
(Byte)
Send command to Z80 (Z80 port &00), Read Z80 reply (Z80
port &0C) |
REG_STATUS_A |
$320001
|
uPD4990
bits, Coin switches [switches active low] |
REG_P2CNT |
$340000
|
Player
2 Controls (DCBArldu) [active low] |
REG_STATUS_B |
$380000
|
Aux
inputs (Start/Select, Memory Card...) [active low] |
REG_POUTPUT |
$380001
|
Joypad
port outputs |
CARD_BANK |
$380011
|
Memory
Card bank select |
REG_SLOT |
$380021
|
Slot
Number (MVS)/REG_POUTPUT mirror (home) |
REG_LEDLATCHES |
$380031
|
LED
Latches (latched on 1->0/falling edge transition) |
REG_LEDDATA |
$380041
|
LED
Output Data |
REG_RTCCTRL |
$380051
|
Strobe/Clock/DIN
for uPD4990 |
REG_COIN1COUNT_HI |
$380061
|
Chute
1 coin counter -> High |
REG_COIN2COUNT_HI |
$380063
|
Chute
2 coin counter -> High |
REG_COIN1LOCK_HI |
$380065
|
Chute
1 coin lockout -> High |
REG_COIN2LOCK_HI |
$380067
|
Chute
2 coin lockout -> High |
REG_RTCWRITE |
$3800D1
|
Write
to RTC |
REG_COIN1COUNT_LO |
$3800E1
|
Chute
1 coin counter -> Low |
REG_COIN2COUNT_LO |
$3800E3
|
Chute
2 coin counter -> Low |
REG_COIN1LOCK_LO |
$3800E5
|
Chute
1 coin lockout -> Low |
REG_COIN2LOCK_LO |
$3800E7
|
Chute
2 coin lockout -> Low |
SYS_NOSHADOW |
$3A0001
|
Normal
output (a.k.a. "SHADOW_OFF","REG_NOSHADOW") |
SYS_BIOSVEC |
$3A0003
|
Use
BIOS vectors (a.k.a. "SYSTEM_ROM","REG_SWPBIOS") |
CARD_ENABLE_1 |
$3A0005
|
Enable
card writes (w/CARD_ENABLE_2). (a.k.a.
"REG_CRDUNLOCK1","IC_WRITE_EI1") |
CARD_DISABLE_1 |
$3A0007
|
Disable
card writes (w/CARD_DISABLE_2). (a.k.a.
"REG_CRDLOCK1","IC_WRITE_DI1") |
CARD_SELECT |
$3A0009
|
Enable
card register select |
SYS_BIOSFIX |
$3A000B
|
Use
BIOS Fix tiles |
SYS_MVSBRAM_LOCK |
$3A000D
|
Write-protect
MVS-only Backup RAM |
PALETTE_BANK1 |
$3A000F
|
(byte)
Palette bank 1 register |
SYS_SHADOW |
$3A0011
|
Darkened
output (a.k.a. "SHADOW_ON","REG_SHADOW") |
SYS_CARTVEC |
$3A0013
|
Use
Cart vectors (a.k.a. "USER_ROM","REG_SWPROM") |
CARD_DISABLE_2 |
$3A0015
|
Disable
card writes (w/CARD_DISABLE_1). (a.k.a.
"REG_CRDLOCK2","IC_WRITE_DI2") |
CARD_ENABLE_2 |
$3A0017
|
Enable
card writes (w/CARD_ENABLE_1). (a.k.a.
"REG_CRDUNLOCK2","IC_WRITE_EI2") |
CARD_NORMAL |
$3A0019
|
Disable
card register select |
SYS_CARTFIX |
$3A001B
|
Use
Cart Fix tiles |
SYS_MVSBRAM_UNLOCK |
$3A001D
|
Unprotect
MVS-only Backup-RAM |
PALETTE_BANK0 |
$3A001F
|
(byte)
Palette bank 0 register |
LSPC_ADDR |
$3C0000
|
VRAM
Address |
LSPC_DATA |
$3C0002
|
VRAM
Data |
LSPC_INCR |
$3C0004
|
VRAM
Increment (1=on 0=off)
|
LSPC_MODE |
$3C0006
|
LSPC
Mode |
LSPC_TIMER_HI |
$3C0008
|
Timer
MSB |
LSPC_TIMER_LO |
$3C000A
|
Timer
LSB |
LSPC_IRQ_ACK |
$3C000C
|
Interrupt
acknowlege |
LSPC_TIMER_STOP |
$3C000E
|
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:
<dataarea name="sprites" size="0x400000">
<rom loadflag="load16_byte" name="202-c1.c1"
offset="0x000000" size="0x100000" crc="479543cf"
sha1="772690c872632320133a799aa41f6e68a8d07a4c" />
<rom loadflag="load16_byte" name="202-c2.c2"
offset="0x000001" size="0x100000" crc="1f6431d5"
sha1="7c90d6ec9df9e6223a066c338b7a7886071370cf" />
<rom loadflag="load16_byte" name="Sprites.c1"
offset="0x100000" size="0x100000" crc="479543cf"
sha1="772690c872632320133a799aa41f6e68a8d07a4c" />
<rom loadflag="load16_byte" name="Sprites.c2"
offset="0x100001" size="0x100000" crc="1f6431d5"
sha1="7c90d6ec9df9e6223a066c338b7a7886071370cf" />
</dataarea>
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 #$0041,$3C0000
;Use Palette 1
move.w #$0100,$3C0002
;PPPPPPPP NNNNAAVH
Palette Tile, Autoanimate Flip
move.w #$0040+2,$3C0000 ;Show Tile 1 from bank $100000
move.w #$2001,$3C0002
;NNNNNNNN Tile
move.w #$0041+2,$3C0000 ;Use Palette 1
move.w #$0100,$3C0002
;PPPPPPPP NNNNAAVH Palette
Tile, Autoanimate Flip
move.w #$8000+1,$3C0000 ;Full size
move.w #$0FFF,$3C0002
;----HHHH VVVVVVVV -
Shrink
move.w #$8200+1,$3C0000 ;Top of screen - 2 tiles tall
move.w #$F402,$3C0002
;YYYYYYYY YCSSSSSS Ypos -
Chain Sprite Size
move.w #$8400+1,$3C0000 ;Left of screen
move.w #$0800,$3C0002
;XXXXXXXX X------- Xpos
;Sprite 2
move.w #$0080,$3C0000
;Show Tile 2 from bank
$100000
move.w #$2002,$3C0002
;NNNNNNNN Tile - my tiles
start at $2000
move.w #$0081,$3C0000
;Use Palette 1
move.w #$0100,$3C0002
;PPPPPPPP NNNNAAVH Palette
Tile, Autoanimate Flip
move.w #$0080+2,$3C0000 ;Show Tile 3 from bank $100000
move.w #$2003,$3C0002
;NNNNNNNN Tile
move.w #$0081+2,$3C0000
;Use Palette 1
move.w #$0100,$3C0002
;PPPPPPPP NNNNAAVH Palette
Tile, Autoanimate Flip
move.w #$8000+2,$3C0000
;Full size
move.w #$0FFF,$3C0002
;----HHHH VVVVVVVV -
Shrink
move.w #$8200+2,$3C0000
;Chain Sprite - Ypos ignored
move.w #$0040,$3C0002
;YYYYYYYY YCSSSSSS Ypos -
Chain Sprite Size
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!
|
NeoGeo Links!
Neo Geo programming for the
absolute beginner - My template Header/footer are based on this!
NeoGeo Programmers Guide PDF
NeoGeoDev.org
| |
Buy my Assembly programming book on Amazon in Print or Kindle!



Available worldwide! Search 'ChibiAkumas' on your local Amazon website!
Click here for more info!
Buy my Assembly programming book on Amazon in Print or Kindle!



Available worldwide! Search 'ChibiAkumas' on your local Amazon website!
Click here for more info!
Buy my Assembly programming book on Amazon in Print or Kindle!



Available worldwide! Search 'ChibiAkumas' on your local Amazon website!
Click here for more info!
|