⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mdfr.cpp

📁 DGen源码最后版本
💻 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 + -