📄 mdfr.cpp
字号:
// DGen v1.11+
// Megadrive 1 Frame module
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "md.h"
int split_screen=0;
int md::run_to_odo(int odo_to)
{
if (pause) return 1;
// THIS FUNCTION IS REALLY A MACRO - it expects star_mz80_on() to have been
// called
int odo_start=0;
#ifdef COMPILE_WITH_STAR
if (cpu_emu==0)
{
odo_start=s68000readOdometer();
s68000exec(odo_to-odo_start);
}
#endif
#ifdef COMPILE_WITH_MUSA
if (cpu_emu==1)
{
odo_start=odo;
odo+=m68k_execute(odo_to-odo_start);
}
#endif
if (z80_online)
{
int wanted=0,did;
mz80GetElapsedTicks(1);
wanted=(odo_to-odo_start)*51/100;
wanted-=z80_extra_cycles;
if (wanted<0) wanted=0;
PROFS("cpu_emu") mz80exec(wanted); PROFE
did=mz80GetElapsedTicks(1);
z80_extra_cycles=did-wanted;
}
return 0;
}
int md::one_frame(
struct bmap *bm,unsigned char retpal[256],
struct sndinfo *sndi)
{
// int frame_len=7189547/60;
int frame_len=7670000/60;
int snd_last_from=0;
star_mz80_on(); // VERY IMPORTANT - Must call before using stars/mz80!!
#ifdef COMPILE_WITH_STAR
if (cpu_emu==0)
s68000tripOdometer(); // odo=0 marks start of frame
#endif
if (cpu_emu==1) odo=0;
coo4=0x36+0x01;
if (vdp.reg[1]&2) coo5^=0x10; // Toggle odd/even in interlace
if ((vdp.reg[1]&0x20)==0) coo5|=0x80;
// when vint disabled, vint happened seems to be permenantly set
for (ras=0;ras<0x106;ras++) // +6 because vcounter E5-EA appears twice!
{
fm_timer_callback();
static int had_a_hint=0;
may_want_to_get_pic(bm,retpal,had_a_hint);
had_a_hint=0;
if (sndi!=NULL)
{
int sndfrom,sndto;
sndfrom=snd_last_from;
sndto =(ras+1)*sndi->len/0x106; if (sndto>sndi->len) sndto=sndi->len;
may_want_to_get_sound(sndi,sndfrom,sndto);
snd_last_from=sndto;
}
if (ras==0xe0) coo5|=0x08; // go into vblank
// Perform V-int if needed
if (ras==0xfe+6)
{
if ((vdp.reg[1]&0x20)&&!pause)
{
#ifdef COMPILE_WITH_STAR
if (cpu_emu==0) s68000interrupt(6,-1);
#endif
#ifdef COMPILE_WITH_MUSA
if (cpu_emu==1) { m68k_assert_irq(6); m68k_clear_irq(6); }
#endif
}
coo5|=0x80; // vint happened
}
if (vdp.reg[1]&0x40)
{
// if display is enabled...
if (ras==0xff+6) coo5&=~0x08; // come out of vblank
}
// Reset 6-button pad toggle after 26? lines
if (aoo3_six_timeout>25) aoo3_six=0;
else aoo3_six_timeout++;
if (aoo5_six_timeout>25) aoo5_six=0;
else aoo5_six_timeout++;
if (ras==0xe0) z80_int_pending=1;
if (z80_int_pending>0 && z80_online && z80.z80interruptState)
{
mz80int(0);
z80_int_pending--;
}
odo_line_start=((ras+0)*frame_len)/0x106;
odo_line_len= (((ras+1)*frame_len)/0x106)-odo_line_start;
// Perform H-int if needed
if (ras>0 && hint_countdown<=0)
{
if ((vdp.reg[0]&0x10)&&!pause)
{
#ifdef COMPILE_WITH_STAR
if (cpu_emu==0) s68000interrupt(4,-1);
#endif
#ifdef COMPILE_WITH_MUSA
if (cpu_emu==1) { m68k_assert_irq(4); m68k_clear_irq(4); }
#endif
}
hint_countdown=vdp.reg[0xa]+1;
had_a_hint=1;
}
coo5|=0x04;
run_to_odo( odo_line_start + odo_line_len*72/418);
coo5&=~0x04;
run_to_odo( odo_line_start + odo_line_len );
if (ras==0 || hint_countdown<=0) hint_countdown=vdp.reg[0xa]+1;
if (hint_countdown>0) hint_countdown--;
}
star_mz80_off(); // VERY IMPORTANT - Must call after using stars/mz80!!
return 0;
}
int md::calculate_hcoord()
{
int x=0,hcoord;
// c00009 is the H counter (I believe it's (h-coord>>1)&0xff)
#ifdef COMPILE_WITH_STAR
if (cpu_emu==0) x=s68000readOdometer()-odo_line_start;
#endif
#ifdef COMPILE_WITH_MUSA
if (cpu_emu==1) x=odo-odo_line_start;
#endif
// hcoord=-56 (inclusive) to 364 (inclusive) in 40 column mode
hcoord=(x*416)/odo_line_len;
hcoord-=56;
return hcoord;
}
unsigned char md::calculate_coo8()
{
int hvcount;
hvcount=ras;
// c00008 is the V counter
if (calculate_hcoord()>=330) hvcount++;
// v counter seems to be a bit ahead of where h counter wraps
if (hvcount>0xea) hvcount-=6; // vcounter E5-EA appears twice!
hvcount&=0xff;
return hvcount;
}
unsigned char md::calculate_coo9()
{
int coo9;
coo9=(calculate_hcoord()>>1)&0xff;
return coo9;
}
// *************************************
// May want to get pic or sound
// *************************************
int md::may_want_to_get_pic(struct bmap *bm,unsigned char retpal[256],int mark)
{
if (bm==NULL) return 0;
if (last_render_method!=render_method) vdp.make_dirty();
if (last_bpp!=bm->bpp) vdp.make_dirty();
if (ras>=0 && ras<224)
{
if (render_method==0)
{
vdp.draw_scanline(bm, ras);
return 0;
}
else if (render_method==2)
{ vdp.draw_md_line(bm,ras,mark); return 0; }
else if (render_method==3)
{
struct dgen_sinfo si;
vdp.get_screen_info(&si);
DrawMDScanline(bm,&si,ras,this);
return 0;
}
}
if (render_method!=1) return 1;
// render method 1
// Render screen in two portions (a bit of raster effects)
if (split_screen)
{
if (ras==112-56 || ras==112+56)
{
int miny=0,maxy=112;
struct dgen_sinfo si;
if (ras>=112) { miny+=112; maxy+=112; }
vdp.get_screen_info(&si);
if (retpal!=NULL)
{
get_md_palette(retpal,si.cram);
draw_md_graphics(bm,retpal,&si,miny,maxy,layer_sel);
}
else
draw_md_graphics(bm,NULL,&si,miny,maxy,layer_sel);
}
}
else if (ras==100)
{
// Render the graphics now
struct dgen_sinfo si;
vdp.get_screen_info(&si);
if (retpal!=NULL)
{
get_md_palette(retpal,si.cram);
draw_md_graphics(bm,retpal,&si,0,224,layer_sel);
}
else
draw_md_graphics(bm,NULL,&si,0,224,layer_sel);
}
return 0;
}
int md::may_want_to_get_sound(struct sndinfo *sndi,int sndfrom,int sndto)
{
if (sndi==NULL) return 1;
int i;
int ssdac=0x00;
if ( (snd_mute&4)==0 && (dac_enable&0x80)) ssdac=dac_data-0x80;
ssdac<<=7;
for (i=sndfrom;i<sndto;i++) sndi->l[i]=ssdac;
// psg adds it in
if ((snd_mute&2)==0)
SN76496Update_16(0,sndi->l+sndfrom,sndto-sndfrom);
// copy mono signal acorss both
memcpy(sndi->r+sndfrom,sndi->l+sndfrom,sizeof(sndi->l[0])*(sndto-sndfrom) );
// ym2612 adds it in
if ((snd_mute&1)==0)
{
FMSAMPLE *trabuf[2];
trabuf[0]=(FMSAMPLE *) sndi->l+sndfrom;
trabuf[1]=(FMSAMPLE *) sndi->r+sndfrom;
int i;
for (i=(mjazz?0:1);i<(mjazz?3:2);i++)
YM2612UpdateOne(i,(void **)trabuf,sndto-sndfrom);
// The above function seems to return SIGNED shorts after all...
// ... bizarre
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -