line.cpp

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

CPP
220
字号
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "md.h"

static inline int a_pixel(void *at,int bpp,int highcol,int white)
{
       if (bpp<=8)  ((unsigned char  *)at)[0]=white?0xff:highcol;
  else if (bpp<=16) ((unsigned short *)at)[0]=white?0xffff:highcol;
  else if (bpp<=24)
  {
    ((unsigned char  *)at)[0]=white?0xff:(highcol&255);
    ((unsigned char  *)at)[1]=white?0xff:((highcol>>8)&255);
    ((unsigned char  *)at)[2]=white?0xff:(highcol>>16);
  }
  else if (bpp<=32) ((unsigned long  *)at)[0]=white?0xffffffff:highcol;
  return 0;
}

int md_vdp::tile_line(unsigned char *at,int bpp,int line,int tile)
{
  // Draw a line (0-7) of the specified tile
  int tile_off,pal_off;
  unsigned char *tilep; unsigned int *palp;
  int x,white=0;

  tile_off=(tile&0x7ff)<<5;
  tilep=vram+tile_off;

  {
    int byt,bit; // Retrieve dirty information down to 32byte level in bits
    byt=tile_off>>8; bit=byt&7; byt>>=3; byt&=0xff;
    if (dirt[0x00+byt]&(1<<bit)) white=1; else white=0;
    dirt[0x00+byt]&=~(1<<bit); // reset dirty flag
  }

  pal_off=(tile&0x6000)>>9;
  palp=highpal+pal_off;

  if (tile&0x1000) line=7-line;
  tilep+=(line&7)<<2;

  for (x=0;x<8;x++)
  {
    int a,tx;
    if (tile&0x0800) tx=7-x; else tx=x;
    a=tilep[tx>>1]; if ((tx&1)==0) a>>=4; a&=15;
    if (a) a_pixel(at,bpp,palp[a],white);
    at+=(bpp+7)>>3;
  }

  return 0;
}

int md_vdp::draw_sprites(unsigned char *bml,int bpp,int line)
{
  static unsigned sprite_order[0x100]={0};
  static int sprite_count=0;
  int may_have_changed=0,spr,i;
  int inc;
  inc=(bpp+7)>>3; // inc = add 1 pixel

  if (dirt[0x30]&(1<<5)) may_have_changed=1; // reg[5] changed
  spr=reg[0x05]<<9;
  if (dirt[0x34]&1)      may_have_changed=1; // VRAM   changed
  // (For more efficiency you may also want to check
  //   if the VRAM affecting the sprites is intact)

  if (may_have_changed)
  {
    // Calculate the sprite order (needs to be rendered backwards)
    sprite_count=0;
    sprite_order[0]=0;
    for (i=1;i<=0x100;i++)
    {
      unsigned char next;
      next=vram[(spr+sprite_order[i-1]*8+3)&0xffff];
      if ((next==0)||(i>=0x100)) { sprite_count=i; break; }
      sprite_order[i]=next;
    }
  }

  for (i=sprite_count-1;i>=0;i--)
  {
    int sprno,x,y,xs,ys,tile,tx,ty;
    int fx,fy;

    sprno=sprite_order[i];
    y=(vram[(spr+sprno*8+0)&0xffff]<<8)+vram[(spr+sprno*8+1)&0xffff];
    x=(vram[(spr+sprno*8+6)&0xffff]<<8)+vram[(spr+sprno*8+7)&0xffff];

    x&=0x1ff;
    if ((reg[12]&6)==6)
    {
      // interlace mode
      y&=0x3ff;
      y>>=1; // interlace mode
    }
    else y&=0x1ff;

    y-=0x80;
    x-=0x80;

    if ((reg[0xc]&1)==0) x+=4*8;
    ys=vram[(spr+sprno*8+2)&0xffff];
    xs=ys>>2; xs&=3; ys&=3; xs++; ys++;
    tile=vram[(spr+sprno*8+4)&0xffff]; tile<<=8;
    tile+=vram[(spr+sprno*8+5)&0xffff];

    fy=(tile&0x1000)?1:0;
    fx=(tile&0x0800)?1:0;
    for (tx=0;tx<xs;tx++)
    {
      for (ty=0;ty<ys;ty++)
      {
        int dx=x+(fx?xs-tx-1:tx)*8, dy=y+(fy?ys-ty-1:ty)*8;

        if (line>=dy && line<dy+8)
        {
          if (dx+8>=0 && dx+16<336)
            tile_line(bml+(dx+8)*inc,bpp,line-dy,tile);
        }
//        if ( ((tile&0x8000)==0x8000) == high )
//          draw_tile(bm,si,dx,dy,tile,ymin,ymax);
        tile++;
      }
    }
  }

  return 0;
}

// (Okay - we have lots of dirt info, but we may not use most of it!)
int md_vdp::draw_md_line(struct bmap *bm,int line,int mark)
{
  unsigned char *bml;
  int c,x;


  {
    // If we changed color depth
    static int last_bpp=-1;
    if (last_bpp!=bm->bpp) memset(dirt,0xff,0x35);
    last_bpp=bm->bpp;
  }

  // We use the global color dirt info
  if (dirt[0x34]&2)
  {
    unsigned char *pc; pc=cram;
    for (c=0;c<64;c++)
    {
      int r,g,b;
      b=(*pc&0x0e)<<4; pc++;
      g=(*pc&0xe0);
      r=(*pc&0x0e)<<4; pc++;
      // Recode into required depth
      if (bm->bpp<=8) highpal[c]=c;
      else if (bm->bpp<=15) highpal[c]=((r>>3)<<10) + ((g>>3)<<5) + (b>>3);
      else if (bm->bpp<=16) highpal[c]=((r>>3)<<11) + ((g>>2)<<5) + (b>>3);
      else if (bm->bpp<=32) highpal[c]=(r<<16) + (g<<8) + b;
    }
  }

  bml=bm->data+(line+8)*bm->pitch;
  {
    int col; unsigned char *pp;
    int inc,x;
    inc=(bm->bpp+7)>>3; // inc = add 1 pixels
    pp=bml+(inc<<3);
    col=highpal[reg[7]&63];
    for (x=0;x<320;x++,pp+=inc)
    {
      if (mark) col=(x&1)?0:0xffffffff;
      a_pixel(pp,bm->bpp,col,0);
    }
  }
  draw_sprites(bml,bm->bpp,line);

/*
  // Fade colors
  if (bm->bpp>=24)
  {
    for (c=0;c<64;c++)
    {
      int r,g,b;
      r=highpal[c]>>16; r&=0xff;
      g=highpal[c]>> 8; g&=0xff;
      b=highpal[c]    ; b&=0xff;
      if (r>0) r--;
      if (g>0) g--;
      if (b>0) b--;
      highpal[c]=(r<<16) + (g<<8) + b;
    }
  }
*/

/*
  // Draw some tiles
  {
    int x,inc;
    static int add=0; add++;
    unsigned char *bmt;
    inc=(bm->bpp+7)&~7; // inc = add 8 pixels
    bmt=(unsigned char *)bml+inc;
    for (x=0;x<40;x++)
    {
      int tile;
      tile=(((line+(add>>9))>>3)*40)+x;
      tile_line(bmt,bm->bpp,(line+(add>>9))&7,tile);
      bmt+=inc;
    }
  }
*/

  memset(dirt,0x00,0x35); // Mark everything as unchanged again

  return 0;
}

⌨️ 快捷键说明

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