Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions cores/sharrier/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
- JTSHARRIER

Sega Space Harrier compatible verilog core for FPGA, built on JTFRAME
(https://github.com/jotego/jtframe) and reusing HDL from Jose Tejada's jtcores.

Space Harrier runs on Sega's Hang-On hardware: two 68000s, an i8751 MCU, a Z80
for sound, a YM2203 and the discrete SegaPCM part, plus the tilemap, sprite and
road generators shared with Hang-On and Enduro Racer. That hardware uses the
same video chips as System 16A, so the tilemap and palette come from jts16.

- Supported Games

Set | Description | Notes
-----------|---------------------------------------|--------------------------------
sharrier | Space Harrier (Rev A, 8751 315-5163A) | Preferred. Clean MCU dump.
sharrier1 | Space Harrier (8751 315-5163) | MCU is flagged BAD_DUMP in MAME

Use the Rev A set where possible. The MCU drives the 68000's interrupt lines and
gates the boot sequence, so a bad MCU dump matters more here than it would
elsewhere.

- Controls

Space Harrier is an analog game. The cabinet has a sprung flight stick and three
fire buttons that all do the same thing; the game reads the stick through an
ADC0804, and the i8751 MCU does the reading, not the main CPU.

Note that Analog stick is the intended control.
D-pad is supported as an option, but the game has no concept of a digital
input, so the pad is converted to a position internally.

The cabinet's stick is an aircraft stick: push up and Harrier goes down.

- QOL Options

Beyond the DIPs, three options are added. All default to the arcade
behaviour, so loading the MRA and changing nothing gives you the original
machine.

Option | Values | Default | What it does
----------------|------------------|---------|--------------------------------------
Stick Direction | Normal / Arcade | Arcade | Y-axis inversion. Arcade matches the cabinet's aircraft stick.
D-Pad Control | Console / Arcade | Arcade | How the d-pad behaves on release. See below.
V Glyph Fix | On / Off | Off | Corrects a glyph drawn wrong in the original ROM. See below.

- The 'V' glyph

The letter "V" is drawn wrong in the original ROM: it rolls over by one, so the
bottom border appears at the top. This is authentic. It looks the same in MAME
and on real hardware. It shows in the test menu and on the scoreboard name
select.

The core is faithful by default. Turning the option On renders a normal V.

- D-Pad Control, and why Arcade is the default

Arcade springs the stick back to centre on release, like the real cabinet.
Basically unplayable with a pad. Console
leaves Harrier where you let go, as the home conversions do.

Arcade is the default for a safety reason also. The two
input paths are summed, so if you are playing with an analog stick and
brush the d-pad in Console mode, that offset stays applied to every reading
afterwards, so your stick's physical centre now maps somewhere else. Arcade
mode decays it away.

- Accuracy Notes

Developed and checked against my original Space Harrier cabinet and known-good
PCBs (Retro Clinic), and Mame. The flight stick calibration, boot timing,
road position, sound balance and video timing were all measured from my Cab.

Game speed was measured against the cabinet over a 30 minute synchronised
recording. The core runs about 0.16% fast, roughly 2.9 seconds in half an hour -
and thats fine.
The schematics were used throughout where possible. The audio
mixing is built from the board's own summing resistors and filter values read
off the sound board sheet. The PPI port assignments,
including the sound CPU reset line, were traced on the schematic and checked
against MAME rather than taken on trust.

Known and not fixed:

- A certain sound effect later in the game can stick on for a while under
heavy activity; this is most likely original behaviour.

- Provenance

Subsystem | Source
-----------------------------------|----------------------------------------
68000 x2, i8255 PPI, YM2203, mixer | JTFRAME (jotego)
Tilemap, palette, priority | jts16 (jotego)
SegaPCM | forked from jtoutrun (jotego)
i8751 MCU | Oregano mc8051 (LGPL), retimed here
Road generator | transcribed from MAME segaic16_road.cpp
Sprite scan and draw | transcribed from MAME sega16sp.cpp
Memory map, I/O, ADC, sound, video | written for this core

The road and sprite routines are the two places where MAME's C++ was read and
re-implemented in verilog. Everything else is either jotego's HDL or new work.

MAME was used for those two because Space Harrier's road and sprite hardware are
their own variants, and no existing jtcores core implements them. Sega's custom
chips have never been decapped, so there is no die shot to work from. MAME's
implementation is the best available description of what they do.

Out Run's sprite zoom enlarges; Space Harrier's only ever shrinks, because the
sprite ROM holds many pre-scaled copies of each object and the hardware
interpolates between them. Porting Out Run's drawer was tried first and came out the wrong
shape, so MAME's description of the actual part was used instead. The road is
the same story: Out Run's generator is a different one.

- Credits and Licence

This core is GPL-3, as JTCORES is.

- Built on JTFRAME and the jts16 / jtoutrun HDL by Jose Tejada (jotego).
Tilemap, palette, priority, 68000, i8255, YM2203 and the SegaPCM module all
come from his work. Please support it: https://patreon.com/jotego
- The 8051 core is Oregano Systems' mc8051 (LGPL), via JTFRAME.
- The road generator and the sprite draw routine are transcribed into verilog
from MAME's segaic16_road.cpp and sega16sp.cpp, BSD-3-Clause, copyright
Aaron Giles. Attribution is retained in those module headers.
- Space Harrier core work by niknak.
- HDL, simulation analysis and documentation written in collaboration with
Claude (Anthropic). Hardware measurement, testing and the judgement calls
on the result were niknak's.
95 changes: 95 additions & 0 deletions cores/sharrier/cfg/files.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@

sharrier:
- get:
- "*.v"
- timing.sdc

- from: 8051
unless: [VERILATOR, IVERILOG]
get:
- mc8051_p.vhd
- mc8051_control_.vhd
- mc8051_control_struc.vhd
- mc8051_core_.vhd
- mc8051_core_struc.vhd
- from: 8051
when: [VERILATOR, IVERILOG]
get:
- mc8051.v

s16:
- get:
- tilemap.yaml
- jts16_colmix.v

jtframe:
- unless: [VERILATOR, IVERILOG]
from: cpu/8051
get:
- control_fsm_.vhd
- control_fsm_rtl.vhd
- control_fsm_rtl_cfg.vhd
- control_mem_.vhd
- control_mem_rtl.vhd
- control_mem_rtl_cfg.vhd
- alumux_.vhd
- alumux_rtl.vhd
- alumux_rtl_cfg.vhd
- alucore_.vhd
- alucore_rtl.vhd
- alucore_rtl_cfg.vhd
- addsub_cy_.vhd
- addsub_cy_rtl.vhd
- addsub_cy_rtl_cfg.vhd
- addsub_ovcy_.vhd
- addsub_ovcy_rtl.vhd
- addsub_ovcy_rtl_cfg.vhd
- addsub_core_.vhd
- addsub_core_struc.vhd
- addsub_core_struc_cfg.vhd
- comb_divider_.vhd
- comb_divider_rtl.vhd
- comb_divider_rtl_cfg.vhd
- comb_mltplr_.vhd
- comb_mltplr_rtl.vhd
- comb_mltplr_rtl_cfg.vhd
- dcml_adjust_.vhd
- dcml_adjust_rtl.vhd
- dcml_adjust_rtl_cfg.vhd
- mc8051_siu_.vhd
- mc8051_siu_rtl.vhd
- mc8051_siu_rtl_cfg.vhd
- mc8051_tmrctr_.vhd
- mc8051_tmrctr_rtl.vhd
- mc8051_tmrctr_rtl_cfg.vhd
- mc8051_alu_.vhd
- mc8051_alu_struc.vhd
- mc8051_alu_struc_cfg.vhd
- mc8051_control_struc_cfg.vhd
- from: cpu
get:
- jtframe_m68k.yaml
- jtframe_z80.yaml
- from: ram
get:
- jtframe_ram_rst.v
- from: clocking
get:
- jtframe_frac_cen.v
- from: ram
get:
- jtframe_dual_ram16.v
- jtframe_ram.v
- jtframe_obj_buffer.v
- from: video
get:
- jtframe_vtimer.v
- jtframe_blank.v
- jtframe_linebuf.v

jt12:
- get:
- jt12_rst.v
- jt03.yaml

jt8255:
80 changes: 80 additions & 0 deletions cores/sharrier/cfg/macros.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# SHARRIER — Space Harrier (Sega Hang-On / Space Harrier hardware)
# NOTE: comments must be on their OWN line. Inline '#' after a macro is NOT
# stripped by the parser and will break the build.

CORENAME=JTSHARRIER
GAMETOP=jtsharrier_game_sdram

JTFRAME_PXLCLK=6

# Space Harrier: analog flight stick + three fire buttons. The test menu lists
# three and they all do the same thing. 5 = those three plus TEST and SERVICE
# as per the cabinet; jtframe shifts start/coin up by itself.
JTFRAME_BUTTONS=5

# THIS CORE MUST NOT USE JTFRAME'S MULTIWAY EMULATION.
# jtframe_multiway is ON BY DEFAULT and takes the analog stick, then PWM-
# MODULATES the digital d-pad bits at 25/50/75% duty off a frame counter
# (jtframe_multiway.v, function pwm) so that games with DIGITAL inputs can be
# played with an analog pad. Space Harrier reads the analog axes directly, and
# jtsharrier_game.v ALSO sums in a digital ramp for pad users -- so those PWM'd
# bits made dig_x/dig_y step by AN_STEP (4) every frame while the raw joyana
# value sat perfectly still. That is the long-standing off-centre stick jitter:
# steps of exactly 4, never at centre (pwm() passes the raw bit
# through when abs[7] is set), and absent at full deflection (abs[6:4]==7 ->
# pwm=1 constantly). It is also why the per-frame sample-and-hold did not fix
# it -- the PWM changes per frame, so each frame latched a different phase.
# The analog siblings outrun and s16 set this too.
JTFRAME_NOMULTIWAY
# SegaPCM is stereo (per-channel pan)
JTFRAME_STEREO

# Real hardware DIPs occupy bits 0-15 (SWA and SWB); extras live at 28-31.
JTFRAME_DIPBASE=16

# Screen: same timing as the Out Run generation (6.2937 MHz pixel clock)
JTFRAME_PLL=jtframe_pll6293
JTFRAME_COLORW=5
JTFRAME_WIDTH=320
JTFRAME_HEIGHT=224

# Clock domain
JTFRAME_CLK48

JTFRAME_HEADER=16
# 64-bit bursts to speed up gfx fetch (tiles + objects)
JTFRAME_BA0_LEN=64
JTFRAME_BA2_LEN=64
JTFRAME_BA3_LEN=64

JTFRAME_OSD_TEST
# No boot logo (avoids needing logodata.hex; saves BRAM)
JTFRAME_OSD_NOLOGO

# ROM regions / SDRAM map (byte offsets in the download image)
JTFRAME_BA1_START = 0x040000
SND_START = 0x050000
PCM_START = 0x058000
JTFRAME_BA2_START = 0x080000
JTFRAME_BA3_START = 0x0A0000
ROAD_START = 0x1A0000
ROAD1_START = 0x1A4000
ZOOM_START = 0x1A8000
# The i8751 program loads as a PROM, not SDRAM. jtframe's prom section (where
# prom_we fires) begins at JTFRAME_PROM_START and must sit AFTER every SDRAM
# region. zoom ends at 0x1AA000, so start the prom section at 0x1B0000 and place
# the MCU there. (Non-BALUT path: is_prom = part_addr >= JTFRAME_PROM_START.)
MCU_START = 0x1B0000
JTFRAME_PROM_START = 0x1B0000

# Heavy core: enable only on the larger platforms
JTFRAME_SKIP

[pocket|mister|sockit|de1soc|de10std|sidi128]
-JTFRAME_SKIP
# Line-based frame buffer for the scaled-sprite engine
JTFRAME_LF_BUFFER

[mister|sockit|de1soc|de10std|sidi128]
# Analog stick vs digital fallback for the flight stick
CORE_OSD=OKM,Control Type,A.Stick,Digital;
90 changes: 90 additions & 0 deletions cores/sharrier/cfg/mame2mra.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# JTSHARRIER MRA generation — first draft.
# Run with Jotego's `jtframe mra` tool against MAME's segahang hash data.
# THE SET WE ACTUALLY SHIP IS THE PARENT, `sharrier` (Rev A):
# mra/Space Harrier (Rev A, 8751 315-5163A).mra -> MCU 315-5163a, crc 203dffeb
# That MCU is a CLEAN DUMP. The clone `sharrier1` goes to _alternatives and its
# MCU (315-5163, crc 52b0c81a) is flagged BAD_DUMP in MAME -- the comment there
# reads "handcrafted from decapped rev a mcu", and `mame sharrier1` prints
# "315-5163.ic32 ROM NEEDS REDUMP" while `mame sharrier` is clean.
# PREFER THE PARENT for anything MCU-related (it drives the 68000 IPL lines, so
# boot sequencing runs through it). `main=` below only picks the MRA the tool
# treats as primary-by-name; both are generated.

[global]
author=["niknak"]

[parse]
sourcefile=[ "segahang.cpp" ]
# Only the Space Harrier machines; drop Hang-On / Enduro / Super Hang-On / bootlegs
main = "sharrier1"

skip.setnames=[
"hangon","hangon1","hangon2","hangonvf",
"shangonro","shangonho","shangonrb","shangonrb2","shangupb",
"enduror","endurora","endurorb","enduror1","endurobl","enduror1d",
"endurob2","endurord"
]
skip.bootlegs=true

[buttons]

Names = [
{ machine="sharrier1", names="Fire,Fire 2,Fire 3,Test,Service" },
{ machine="sharrier", names="Fire,Fire 2,Fire 3,Test,Service" },
]

[dipsw]
delete=[{names=["Unused","Unknown"]}]
bitcnt = 29


[[dipsw.extra]]
name = "Stick Direction"
bits = "28"
options = "Normal,Arcade"

[[dipsw.extra]]
name = "D-Pad Control"
bits = "29"
options = "Console,Arcade"

[[dipsw.extra]]
name = "V Glyph Fix"
bits = "31"
options = "On,Off"

[header]
fill=0

[ROM]
regions = [
{ name="maincpu", width=16, reverse=true },
{ name="subcpu", start="JTFRAME_BA1_START", width=16, reverse=true },
{ name="soundcpu", start="SND_START" },
{ name="pcm", start="PCM_START", No_offset=true },
{ name="mcu", start="MCU_START", No_offset=true },
# tiles: 3bpp planar, 3 ROMs
{ name="gfx1", start="JTFRAME_BA2_START", width=32, sequence=[0,1,2,2] },
# sprites: 32-bit little endian, 32 ROMs
{ name="sprites", start="JTFRAME_BA3_START", width=32, No_offset=true },
{ name="segaic16road", start="ROAD_START", width=16, No_offset=true, singleton=true },
{ name="sprites:zoom", start="ZOOM_START", No_offset=true },
]

order = [
"maincpu", "subcpu", "soundcpu", "pcm",
"gfx1", "sprites", "segaic16road", "sprites:zoom",
# mcu is a PROM (loads via prom_we), so it MUST come last, after all SDRAM
# regions, so it lands in the prom section at/after JTFRAME_PROM_START.
"mcu"
]


[[audio.volume]]
value = 160


[[dipsw.rename]]
name = "Bonus Life"

values = ["7M", "5M"]
Loading
Loading