CD32 FMV cartridge

This commit is contained in:
Toni Wilen 2014-07-10 17:16:41 +03:00
parent 99879e3e14
commit 79acacb3ec
12 changed files with 1572 additions and 256 deletions

2
ar.cpp
View File

@ -1643,6 +1643,8 @@ int action_replay_load (void)
if (_tcslen (currprefs.cartfile) == 0)
return 0;
if (currprefs.cs_cd32fmv)
return 0;
rd = getromdatabypath (currprefs.cartfile);
if (rd) {
if (rd->id == 62)

File diff suppressed because it is too large Load Diff

110
cd32_fmv_genlock.cpp Normal file
View File

@ -0,0 +1,110 @@
/*
* UAE - The Un*x Amiga Emulator
*
* CD32 FMV video genlock
*
* Copyright 2014 Toni Wilen
*
*/
#include "sysconfig.h"
#include "sysdeps.h"
#include "options.h"
#include "cd32_fmv.h"
#include "xwin.h"
static uae_u8 *mpeg_out_buffer;
static int mpeg_width, mpeg_height;
static uae_u32 fmv_border_color;
int cd32_fmv_active;
// According to schematics there is at least 3 (possible more)
// "genlock modes" but they seem to be unused, at least ROM
// mpeg player software never sets any genlock bits.
// this is probably not how it actually works.
#define GENLOCK_VAL 0x20
#define MPEG_PIXBYTES 4
#define MAX_MPEG_WIDTH 352
#define MAX_MPEG_HEIGHT 288
void cd32_fmv_new_border_color(uae_u32 bordercolor)
{
fmv_border_color = bordercolor;
}
void cd32_fmv_new_image(int w, int h, uae_u8 *s)
{
if (!mpeg_out_buffer)
mpeg_out_buffer = xmalloc(uae_u8, MAX_MPEG_WIDTH * MAX_MPEG_HEIGHT * MPEG_PIXBYTES);
if (s == NULL || w > MAX_MPEG_WIDTH || h > MAX_MPEG_HEIGHT) {
memset(mpeg_out_buffer, 0, MAX_MPEG_WIDTH * MAX_MPEG_HEIGHT * MPEG_PIXBYTES);
mpeg_width = MAX_MPEG_WIDTH;
mpeg_height = MAX_MPEG_HEIGHT;
return;
}
memcpy(mpeg_out_buffer, s, w * h * MPEG_PIXBYTES);
mpeg_width = w;
mpeg_height = h;
}
void cd32_fmv_state(int state)
{
cd32_fmv_active = state;
}
// slow software method but who cares.
void cd32_fmv_genlock(struct vidbuffer *vbin, struct vidbuffer *vbout)
{
int hoffset, voffset, mult;
int w = vbin->outwidth;
int h = vbin->outheight;
int d = vbin->pixbytes;
mult = 1;
for (;;) {
if (mult < 4 && mpeg_width * (mult << 1) <= w && mpeg_height * (mult << 1) <= h) {
mult <<= 1;
}
else {
break;
}
}
hoffset = (w / mult - mpeg_width) / 2;
voffset = (h / mult - mpeg_height) / 2;
if (hoffset < 0)
hoffset = 0;
if (voffset < 0)
voffset = 0;
for (int hh = 0, sh = -voffset; hh < h; sh++, hh += mult) {
for (int h2 = 0; h2 < mult; h2++) {
uae_u8 *d8 = vbout->bufmem + vbout->rowbytes * (hh + h2 + voffset);
uae_u32 *d32 = (uae_u32*)d8;
uae_u8 *s8 = vbin->bufmem + vbin->rowbytes * (hh + h2 + voffset) ;
uae_u32 *srcp = NULL;
if (sh >= 0 && sh < mpeg_height)
srcp = (uae_u32*)(mpeg_out_buffer + sh * mpeg_width * MPEG_PIXBYTES);
for (int ww = 0, sw = -hoffset; ww < w; sw++, ww += mult) {
uae_u32 sv = fmv_border_color;
if (sw >= 0 && sw < mpeg_width && srcp)
sv = srcp[sw];
for (int w2 = 0; w2 < mult; w2++) {
uae_u32 v;
if (s8[0] >= GENLOCK_VAL) {
v = *((uae_u32*)s8);
} else {
v = sv;
}
*d32++ = v;
s8 += d;
}
}
}
}
}

View File

@ -180,7 +180,7 @@ static const TCHAR *magiccursors[] = { _T("both"), _T("native"), _T("host"), 0 }
static const TCHAR *autoscale[] = { _T("none"), _T("auto"), _T("standard"), _T("max"), _T("scale"), _T("resize"), _T("center"), _T("manual"), _T("integer"), _T("integer_auto"), 0 };
static const TCHAR *autoscale_rtg[] = { _T("resize"), _T("scale"), _T("center"), _T("integer"), 0 };
static const TCHAR *joyportmodes[] = { _T(""), _T("mouse"), _T("mousenowheel"), _T("djoy"), _T("gamepad"), _T("ajoy"), _T("cdtvjoy"), _T("cd32joy"), _T("lightpen"), 0 };
static const TCHAR *joyaf[] = { _T("none"), _T("normal"), _T("toggle"), 0 };
static const TCHAR *joyaf[] = { _T("none"), _T("normal"), _T("toggle"), _T("always"), 0 };
static const TCHAR *epsonprinter[] = { _T("none"), _T("ascii"), _T("epson_matrix_9pin"), _T("epson_matrix_24pin"), _T("epson_matrix_48pin"), 0 };
static const TCHAR *aspects[] = { _T("none"), _T("vga"), _T("tv"), 0 };
static const TCHAR *vsyncmodes[] = { _T("false"), _T("true"), _T("autoswitch"), 0 };
@ -1391,8 +1391,9 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
cfgfile_dwrite_bool (f, _T("ksmirror_a8"), p->cs_ksmirror_a8);
cfgfile_dwrite_bool (f, _T("cd32cd"), p->cs_cd32cd);
cfgfile_dwrite_bool (f, _T("cd32c2p"), p->cs_cd32c2p);
cfgfile_dwrite_bool (f, _T("cd32nvram"), p->cs_cd32nvram);
cfgfile_dwrite_bool (f, _T("cdtvcd"), p->cs_cdtvcd);
cfgfile_dwrite_bool(f, _T("cd32nvram"), p->cs_cd32nvram);
cfgfile_dwrite_bool(f, _T("cd32fmv"), p->cs_cd32fmv);
cfgfile_dwrite_bool(f, _T("cdtvcd"), p->cs_cdtvcd);
cfgfile_dwrite_bool (f, _T("cdtvram"), p->cs_cdtvram);
cfgfile_dwrite (f, _T("cdtvramcard"), _T("%d"), p->cs_cdtvcard);
cfgfile_dwrite_str (f, _T("ide"), p->cs_ide == IDE_A600A1200 ? _T("a600/a1200") : (p->cs_ide == IDE_A4000 ? _T("a4000") : _T("none")));
@ -3514,8 +3515,9 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH
|| cfgfile_yesno (option, value, _T("cpu_no_unimplemented"), &p->int_no_unimplemented)
|| cfgfile_yesno (option, value, _T("cd32cd"), &p->cs_cd32cd)
|| cfgfile_yesno (option, value, _T("cd32c2p"), &p->cs_cd32c2p)
|| cfgfile_yesno (option, value, _T("cd32nvram"), &p->cs_cd32nvram)
|| cfgfile_yesno (option, value, _T("cdtvcd"), &p->cs_cdtvcd)
|| cfgfile_yesno(option, value, _T("cd32nvram"), &p->cs_cd32nvram)
|| cfgfile_yesno(option, value, _T("cd32fmv"), &p->cs_cd32fmv)
|| cfgfile_yesno(option, value, _T("cdtvcd"), &p->cs_cdtvcd)
|| cfgfile_yesno (option, value, _T("cdtvram"), &p->cs_cdtvram)
|| cfgfile_yesno (option, value, _T("a1000ram"), &p->cs_a1000ram)
|| cfgfile_yesno (option, value, _T("pcmcia"), &p->cs_pcmcia)
@ -5308,7 +5310,7 @@ void default_prefs (struct uae_prefs *p, int type)
p->cs_mbdmac = 0;
p->a2091 = 0;
p->a4091 = 0;
p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = false;
p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = p->cs_cd32fmv = false;
p->cs_cdtvcd = p->cs_cdtvram = false;
p->cs_cdtvcard = 0;
p->cs_pcmcia = 0;
@ -5562,7 +5564,7 @@ static void buildin_default_prefs (struct uae_prefs *p)
p->cs_mbdmac = 0;
p->a2091 = false;
p->a4091 = false;
p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = false;
p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = p->cs_cd32fmv = false;
p->cs_cdtvcd = p->cs_cdtvram = p->cs_cdtvcard = false;
p->cs_ide = 0;
p->cs_pcmcia = 0;
@ -5810,10 +5812,10 @@ static int bip_cdtv (struct uae_prefs *p, int config, int compa, int romcheck)
static int bip_cd32 (struct uae_prefs *p, int config, int compa, int romcheck)
{
int roms[2];
int roms[3];
buildin_default_prefs_68020 (p);
p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = 1;
p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = true;
p->nr_floppies = 0;
p->floppyslots[0].dfxtype = DRV_NONE;
p->floppyslots[1].dfxtype = DRV_NONE;
@ -5834,7 +5836,10 @@ static int bip_cd32 (struct uae_prefs *p, int config, int compa, int romcheck)
return 0;
}
if (config > 0) {
roms[0] = 23;
p->cs_cd32fmv = true;
roms[0] = 74;
roms[1] = 23;
roms[2] = -1;
if (!configure_rom (p, roms, romcheck))
return 0;
}
@ -6135,7 +6140,7 @@ int built_in_chipset_prefs (struct uae_prefs *p)
p->cs_ksmirror_e0 = 0;
break;
case CP_CD32: // CD32
p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = 1;
p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = true;
p->cs_ksmirror_e0 = 0;
p->cs_ksmirror_a8 = 1;
p->cs_ciaoverlay = 0;

View File

@ -44,6 +44,7 @@
#endif
#include "debug.h"
#include "akiko.h"
#include "cd32_fmv.h"
#include "cdtv.h"
#if defined(ENFORCER)
#include "enforcer.h"
@ -202,6 +203,7 @@ int firstblankedline;
static int equ_vblank_endline = EQU_ENDLINE_PAL;
static bool equ_vblank_toggle = true;
double vblank_hz = VBLANK_HZ_PAL, fake_vblank_hz, vblank_hz_stored, vblank_hz_nom;
double hblank_hz;
static float vblank_hz_lof, vblank_hz_shf, vblank_hz_lace;
static int vblank_hz_mult, vblank_hz_state;
static struct chipset_refresh *stored_chipset_refresh;
@ -3504,6 +3506,9 @@ int vsynctimebase_orig;
void compute_vsynctime (void)
{
double svpos = maxvpos_nom;
double shpos = maxhpos_short;
fake_vblank_hz = 0;
vblank_hz_mult = 0;
vblank_hz_state = 1;
@ -3529,21 +3534,20 @@ void compute_vsynctime (void)
updatedisplayarea ();
}
#endif
if (islinetoggle ()) {
shpos += 0.5;
}
if (interlace_seen) {
svpos += 0.5;
} else if (lof_current) {
svpos += 1.0;
}
if (currprefs.produce_sound > 1) {
double svpos = maxvpos_nom;
double shpos = maxhpos_short;
if (islinetoggle ()) {
shpos += 0.5;
}
if (interlace_seen) {
svpos += 0.5;
} else if (lof_current) {
svpos += 1.0;
}
double clk = svpos * shpos * fake_vblank_hz;
//write_log (_T("SNDRATE %.1f*%.1f*%.6f=%.6f\n"), svpos, shpos, fake_vblank_hz, clk);
update_sound (clk);
}
cd32_fmv_set_sync(svpos);
}
@ -3770,12 +3774,14 @@ void compute_framesync (void)
compute_vsynctime ();
hblank_hz = (double)(currprefs.ntscmode ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) / (maxhpos + (islinetoggle() ? 0.5 : 0));
write_log (_T("%s mode%s%s V=%.4fHz H=%0.4fHz (%dx%d+%d) IDX=%d (%s) D=%d RTG=%d/%d\n"),
isntsc ? _T("NTSC") : _T("PAL"),
islace ? _T(" lace") : (lof_lace ? _T(" loflace") : _T("")),
doublescan > 0 ? _T(" dblscan") : _T(""),
vblank_hz,
(double)(currprefs.ntscmode ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) / (maxhpos + (islinetoggle () ? 0.5 : 0)),
hblank_hz,
maxhpos, maxvpos, lof_store ? 1 : 0,
cr ? cr->index : -1,
cr != NULL && cr->label != NULL ? cr->label : _T("<?>"),
@ -4611,6 +4617,7 @@ static void rethink_intreq (void)
#endif
#ifdef CD32
rethink_akiko ();
rethink_cd32fmv();
#endif
rethink_gayle ();
}
@ -7064,6 +7071,9 @@ static void vsync_handler_pre (void)
#ifdef RETROPLATFORM
rp_vsync ();
#endif
#ifdef CD32
cd32_fmv_vsync_handler();
#endif
if (!vsync_rendered) {
frame_time_t start, end;
@ -7483,6 +7493,7 @@ static void hsync_handler_pre (bool onvsync)
#endif
#ifdef CD32
AKIKO_hsync_handler ();
cd32_fmv_hsync_handler();
#endif
#ifdef CDTV
CDTV_hsync_handler ();

View File

@ -49,6 +49,7 @@ happening, all ports should restrict window widths to be multiples of 16 pixels.
#include "statusline.h"
#include "inputdevice.h"
#include "debug.h"
#include "cd32_fmv.h"
extern bool emulate_specialmonitors (struct vidbuffer*, struct vidbuffer*);
@ -3125,6 +3126,16 @@ bool draw_frame (struct vidbuffer *vb)
return true;
}
static void setnativeposition(struct vidbuffer *vb)
{
vb->inwidth = gfxvidinfo.drawbuffer.inwidth;
vb->inheight = gfxvidinfo.drawbuffer.inheight;
vb->inwidth2 = gfxvidinfo.drawbuffer.inwidth2;
vb->inheight2 = gfxvidinfo.drawbuffer.inheight2;
vb->outwidth = gfxvidinfo.drawbuffer.outwidth;
vb->outheight = gfxvidinfo.drawbuffer.outheight;
}
static void finish_drawing_frame (void)
{
int i;
@ -3172,14 +3183,8 @@ static void finish_drawing_frame (void)
if (currprefs.monitoremu && gfxvidinfo.tempbuffer.bufmem_allocated) {
if (emulate_specialmonitors (vb, &gfxvidinfo.tempbuffer)) {
vb = gfxvidinfo.outbuffer = &gfxvidinfo.tempbuffer;
if (vb->nativepositioning) {
vb->inwidth = gfxvidinfo.drawbuffer.inwidth;
vb->inheight = gfxvidinfo.drawbuffer.inheight;
vb->inwidth2 = gfxvidinfo.drawbuffer.inwidth2;
vb->inheight2 = gfxvidinfo.drawbuffer.inheight2;
vb->outwidth = gfxvidinfo.drawbuffer.outwidth;
vb->outheight = gfxvidinfo.drawbuffer.outheight;
}
if (vb->nativepositioning)
setnativeposition(vb);
gfxvidinfo.drawbuffer.tempbufferinuse = true;
if (!specialmonitoron)
compute_framesync ();
@ -3194,6 +3199,19 @@ static void finish_drawing_frame (void)
}
}
if (!currprefs.monitoremu && gfxvidinfo.tempbuffer.bufmem_allocated && currprefs.cs_cd32fmv) {
if (cd32_fmv_active) {
cd32_fmv_genlock(vb, &gfxvidinfo.tempbuffer);
vb = gfxvidinfo.outbuffer = &gfxvidinfo.tempbuffer;
setnativeposition(vb);
gfxvidinfo.drawbuffer.tempbufferinuse = true;
do_flush_screen(vb, 0, vb->outheight);
didflush = true;
} else {
gfxvidinfo.drawbuffer.tempbufferinuse = false;
}
}
if (!didflush)
do_flush_screen (vb, first_drawn_line, last_drawn_line);
}

View File

@ -1520,15 +1520,11 @@ void expamem_reset (void)
}
#endif
#ifdef CD32
if (currprefs.cs_cd32cd && currprefs.fastmem_size == 0 && currprefs.chipmem_size <= 0x200000) {
int ids[] = { 23, -1 };
struct romlist *rl = getromlistbyids (ids);
if (rl && !_tcscmp (rl->path, currprefs.cartfile)) {
card_flags[cardno] = 0;
card_name[cardno] = _T("CD32MPEG");
card_init[cardno] = expamem_init_cd32fmv;
card_map[cardno++] = expamem_map_cd32fmv;
}
if (currprefs.cs_cd32cd && currprefs.fastmem_size == 0 && currprefs.chipmem_size <= 0x200000 && currprefs.cs_cd32fmv) {
card_flags[cardno] = 0;
card_name[cardno] = _T("CD32MPEG");
card_init[cardno] = expamem_init_cd32fmv;
card_map[cardno++] = expamem_map_cd32fmv;
}
#endif
#ifdef A2065

View File

@ -1,2 +1,15 @@
extern void cd32_fmv_init (uaecptr);
extern void cd32_fmv_reset(void);
extern void cd32_fmv_free(void);
extern void rethink_cd32fmv(void);
extern void cd32_fmv_hsync_handler(void);
extern void cd32_fmv_vsync_handler(void);
extern void cd32_fmv_state(int state);
extern void cd32_fmv_new_image(int, int, uae_u8*);
extern void cd32_fmv_genlock(struct vidbuffer*, struct vidbuffer*);
extern void cd32_fmv_new_border_color(uae_u32);
extern void cd32_fmv_set_sync(double svpos);
extern int cd32_fmv_active;

View File

@ -128,6 +128,7 @@ extern int maxvpos, maxvpos_nom, maxvpos_display;
extern int hsyncstartpos, hsyncendpos;
extern int minfirstline, vblank_endline, numscrlines;
extern double vblank_hz, fake_vblank_hz;
extern double hblank_hz;
extern int vblank_skip, doublescan;
extern bool programmedmode;

View File

@ -176,7 +176,7 @@ struct uaedev_config_data
int unitnum; // scsi unit number (if tape currently)
};
enum { CP_GENERIC = 1, CP_CDTV, CP_CD32, CP_A500, CP_A500P, CP_A600, CP_A1000,
enum { CP_GENERIC = 1, CP_CDTV, CP_CD32, CP_CD32FMV, CP_A500, CP_A500P, CP_A600, CP_A1000,
CP_A1200, CP_A2000, CP_A3000, CP_A3000T, CP_A4000, CP_A4000T };
#define IDE_A600A1200 1
@ -420,6 +420,7 @@ struct uae_prefs {
bool cs_cd32cd;
bool cs_cd32c2p;
bool cs_cd32nvram;
bool cs_cd32fmv;
bool cs_cdtvcd;
bool cs_cdtvram;
int cs_cdtvcard;

View File

@ -38,6 +38,7 @@
#include "scsidev.h"
#include "uaeserial.h"
#include "akiko.h"
#include "cd32_fmv.h"
#include "cdtv.h"
#include "savestate.h"
#include "filesys.h"
@ -205,9 +206,15 @@ void fixup_prefs_dimensions (struct uae_prefs *prefs)
if (prefs->gf[i].gfx_filter == 0 && ((prefs->gf[i].gfx_filter_autoscale && !prefs->gfx_api) || (prefs->gfx_apmode[APMODE_NATIVE].gfx_vsyncmode))) {
prefs->gf[i].gfx_filter = 1;
}
if (i == 0 && prefs->gf[i].gfx_filter == 0 && prefs->monitoremu) {
error_log (_T("A2024 and Graffiti require at least null filter enabled."));
prefs->gf[i].gfx_filter = 1;
if (i == 0) {
if (prefs->gf[i].gfx_filter == 0 && prefs->monitoremu) {
error_log(_T("A2024 and Graffiti require at least null filter enabled."));
prefs->gf[i].gfx_filter = 1;
}
if (prefs->gf[i].gfx_filter == 0 && prefs->cs_cd32fmv) {
error_log(_T("CD32 MPEG module overlay support require at least null filter enabled."));
prefs->gf[i].gfx_filter = 1;
}
}
}
}
@ -962,6 +969,7 @@ void do_leave_program (void)
#endif
#ifdef CD32
akiko_free ();
cd32_fmv_free();
#endif
if (! no_gui)
gui_exit ();

View File

@ -538,11 +538,17 @@ void *shmat (int shmid, void *shmaddr, int shmflg)
shmaddr=natmem_offset + 0xf00000;
got = TRUE;
readonly = TRUE;
} else if(!_tcscmp (shmids[shmid].name, _T("rtarea"))) {
shmaddr=natmem_offset + rtarea_base;
} else if (!_tcscmp(shmids[shmid].name, _T("rtarea"))) {
shmaddr = natmem_offset + rtarea_base;
got = TRUE;
readonly = TRUE;
readonlysize = RTAREA_TRAPS;
} else if (!_tcscmp(shmids[shmid].name, _T("fmv_rom"))) {
got = TRUE;
shmaddr = natmem_offset + 0x200000;
} else if (!_tcscmp(shmids[shmid].name, _T("fmv_ram"))) {
got = TRUE;
shmaddr = natmem_offset + 0x280000;
} else if(!_tcscmp (shmids[shmid].name, _T("fast"))) {
got = TRUE;
if (size < 524288) {