mem.cpp

来自「DGen源码最后版本」· C++ 代码 · 共 364 行

CPP
364
字号
// DGen v1.11+
// Megadrive C++ module - misc memory

#include <stdio.h>
#include "md.h"
// md.h also has include fm.h

// This is to handle memory accesses outside of ROM and RAM
// e.g. c00000 and a00000 addresses
// REMEMBER NOT TO USE ANY STATIC variables, because they
// will exist thoughout ALL megadrives!

unsigned char md::z80_read(unsigned int a)
{
  if (a<0x2000) return z80ram[a&0xffff];


  if ((a&0xfffc)==0x4000) // 00 01 02 03 - not sure about reads
  {
    return myfm_read(a&3);
  }

  if (a>=0x8000)
  {
    int addr68k;
    addr68k=z80_bank68k<<15;
    addr68k+=a&0x7fff;

    return misc_readbyte(addr68k);
  }

//  dprintf("z80 read %.8x\n",a);

  return 0;
}

unsigned short md::z80_port_read(unsigned short a)
{
  int ret=0;

//  dprintf("z80 port read %.2x return %.4x\n",a,ret);

  return ret;
}
void md::z80_port_write(unsigned short a,unsigned char v)
{
//  dprintf("z80 port write %.2x %.2x\n",a,v);
}


void md::z80_write(unsigned int a,unsigned char v)
{
  if ((a&0xfffc)==0x4000) // 00 01 02 03
  {
    myfm_write(a&3,v,1);
    return ;
  }
  if (a==0x7f11)
  { mysn_write(v); return; }

  if (a==0x6000)
  {
    z80_bank68k>>=1;
    z80_bank68k+=(v&1)<<8;
    z80_bank68k&=0x1ff; // 9 bits and filled in the new top one
    return ;
  }
  if (a<0x2000) { z80ram[a&0xffff]=v; return; }


  if (a>=0x8000)
  {
    int addr68k;
    addr68k=z80_bank68k<<15;
    addr68k+=a&0x7fff;
    misc_writebyte(addr68k,v);
    return;
  }

//  dprintf("z80 write %.4x %.2x\n",a,v);
  return;
}


unsigned md::misc_readbyte(unsigned a)
{
  unsigned char ret=0;
  a&=0x00ffffff; // in case stars didn't clip to 24-bit bus

  // In case it's a rom read after all
  if (a<0xa00000)
  {
    // Saveram
    if (saveram!=NULL && save_len>0) if(a >= save_start) 
      if((a - save_start) < save_len) 
        { return saveram[(a^1) - save_start]; }
    if ((signed)(a^1)<romlen) { ret=rom[(a^1)]; goto end; }
  }

  // In case it's a ram read after all
  if (a>=0xe00000) if (a<=0xffffff) { ret=ram[(a^1)&0xffff]; goto end; }

  // GFX data read (byte)
  if ((a&0xfffffffe)==0x00c00000) // 00 or 01
    { ret=vdp.readbyte(); goto end; }


  if ((a&0xfffffffc)==0xa04000)
  {
    ret=myfm_read(a&3); goto end;
  }

  if ((a>=0xa00000)&&(a<0xa08000))
  {
    // Read from z80's memory
    ret=z80_read(a&0x7fff); goto end;
  }

  // I/O port access
  if ((a&0xfffffe)==0xa10002)
  {
    if (aoo3_six==3)
    {
      // Extended pad info
      if (aoo3_toggle==0) ret=((pad[0]>>8)&0x30)+0x00;
      else ret=((pad[0])&0x30)+0x40+((pad[0]>>16)&0xf);
    }
    else
    {
      if (aoo3_toggle==0)
      {
        if (aoo3_six==4) ret=((pad[0]>>8)&0x30)+0x00+0x0f;
        else             ret=((pad[0]>>8)&0x30)+0x00+(pad[0]&3);
      }
      else ret=((pad[0])&0x30)+0x40+(pad[0]&15);
    }
    goto end;
  }

  if ((a&0xfffffe)==0xa10004)
  {
    if (aoo5_six==3)
    {
      // Extended pad info
      if (aoo5_toggle==0x00) ret=((pad[1]>>8)&0x30)+0x00;
      else ret=((pad[1])&0x30)+0x40+((pad[1]>>16)&0xf);
    }
    else
    {
      if (aoo5_toggle==0x00)
      {
        if (aoo5_six==4) ret=((pad[1]>>8)&0x30)+0x00+0x0f;
        else             ret=((pad[1]>>8)&0x30)+0x00+(pad[1]&3);
      }
      else ret=((pad[1])&0x30)+0x40+(pad[1]&15);
    }
    goto end;
  }

  if (a==0xa10001)
  {
    // overseas/pal/disk/0/ md version (0-f) - may make games act different!
    if ((country_ver&0xff0)==0xff0)
    {
      // autodetect country
      int headcode=0x80,avail=0;
      int i;
      for (i=0;i<3;i++)
      {
        int ch=misc_readbyte(0x1f0+i);
             if (ch=='U') avail|=1;
        else if (ch=='E') avail|=2;
        else if (ch=='J') avail|=4;
      }
           if (avail&1) headcode=0x80;
      else if (avail&2) headcode=0xc0;
      else if (avail&4) headcode=0x00;
      ret=headcode+(country_ver&0x0f);
    }
    else ret=country_ver;
    goto end;
  }

  if (a==0xa11000) {ret=0xff; goto end; }
  if (a==0xa11001) {ret=0xff; goto end; }
  if (a==0xa11100)
  {
    ret=z80_online; goto end;
  }
  if (a==0xa11101) {ret=0x00; goto end; }
  if (a==0xa11200) {ret=0xff; goto end; }
  if (a==0xa11201) {ret=0xff; goto end; }

  // Genecyst style - toggles fifo full/empty
  if (a==0xc00004)
  {
    // This is the genecyst fudge for FIFO full/empty
    coo4^=0x03;
    ret=coo4; goto end;
  }
  if (a==0xc00005)
  {
    // This is the genecyst fudge for in h-blank
    //coo5^=0x04;
    ret=coo5; goto end;
  }

  if (a==0xc00008) { ret=calculate_coo8(); goto end; }
  if (a==0xc00009) { ret=calculate_coo9(); goto end; }


  end:
  return ret;
}

void md::misc_writebyte(unsigned a,unsigned d)
{
  a&=0x00ffffff; // in case stars didn't clip to 24-bit bus

  // In case it's a ram write after all
  // Saveram write
  if (saveram!=NULL && save_len>0) if(a >= save_start)
    if ((a - save_start) < save_len)
      { saveram[(a^1) - save_start] = d; return; }

  if (a>=0xe00000) if (a<=0xffffff) { ram[(a^1)&0xffff]=d; goto end; }

  // GFX data write (byte)
  if ((a&0xfffffffe)==0x00c00000) // 00 or 01
    { vdp.writebyte(d); goto end; }

  if ((a&0xfffffffc)==0xa04000)
  {
    myfm_write(a&3,d,1);
    goto end;
  }

  if (a==0xc00011)
  {
    mysn_write(d); goto end;
  }

  if (a==0xa11100)
  {
//d8 (W) 0: BUSREQ CANCEL
//       1: BUSREQ REQUEST
    if (d==1) z80_online=0;
    else z80_online=1;
    goto end;
  }
  if (a==0xa11101) goto end;
  if (a==0xa11200)
  {
    if (d==0)
      mz80reset();
    goto end;
  }
  if (a==0xa11201) goto end;

  if ((a>=0xa00000)&&(a<0xa08000))
  {
    // Write into z80's memory
    z80_write(a&0x7fff,d);
    goto end;
  }

  // I/O port access
  if (a==0xa10003)
  {
    if (aoo3_six>=0 && (d&0x40)==0 && aoo3_toggle ) aoo3_six++;

    if (aoo3_six>0xc00000) aoo3_six&=~0x400000;
    // keep it circling around a high value

    if (d&0x40) aoo3_toggle=1; else aoo3_toggle=0;
    aoo3_six_timeout=0;
    goto end;
  }
  if (a==0xa10005)
  {
    if (aoo5_six>=0 && (d&0x40)==0 && aoo5_toggle ) aoo5_six++;

    if (aoo5_six>0xc00000) aoo5_six&=~0x400000;
    // keep it circling around a high value

    if (d&0x40) aoo5_toggle=1; else aoo5_toggle=0;
    aoo5_six_timeout=0;
    goto end;
  }

//  dprintf("unhandled: writeb(%.6x,%.2x)\n",a,d);

  end:
  return;
}

unsigned md::misc_readword(unsigned a)
{
  unsigned int ret=0;

  a&=0x00ffffff; // in case stars didn't clip to 24-bit bus

  if ((a&0xfffffffc)==0x00c00000) // 00 or 02
  {
    ret=vdp.readword();
    goto end;
  }

  // else pass onto readbyte
  ret =misc_readbyte(a)<<8;
  ret|=misc_readbyte(a+1);
  goto end;

  end:
  return ret;
}

void md::misc_writeword(unsigned a,unsigned d)
{
  a&=0x00ffffff; // in case stars didn't clip to 24-bit bus

  // GFX data write (word)
  if ((a&0xfffffffc)==0x00c00000) // 00 or 02
  {
    vdp.writeword(d);
    goto end;
  }

  if ((a&0xfffffffc)==0x00c00004) // 04 or 06
  {
    if (coo_waiting)
    {
      // Okay completed the vdp command
      coo_cmd|=d; coo_waiting=0; 

      vdp.command(coo_cmd);
      goto end;
    }
    if ((d&0xc000)==0x8000)
    {
      int addr; addr=d>>8; addr&=0x1f;
      if (vdp.reg[addr]!=(d&0xff))
      {
        // Store dirty information down to 1byte level in bits
        int byt,bit;
        byt=addr; bit=byt&7; byt>>=3; byt&=0x03;
        vdp.dirt[0x30+byt]|=(1<<bit); vdp.dirt[0x34]|=8;
      }
      vdp.reg[addr]=d&0xff;
      goto end;
    }
    coo_cmd=d<<16; coo_waiting=1;
    goto end;
  }

  // else pass onto writebyte
  misc_writebyte(a,d>>8);
  misc_writebyte(a+1,d&255);

  end:
  return;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?