Advertisement
Guest User

meisei_vdp

a guest
May 17th, 2014
298
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 26.62 KB | None | 0 0
  1. #include "global.h"
  2. #include "io.h"
  3. #include "z80.h"
  4. #include "vdp.h"
  5. #include "draw.h"
  6. #include "crystal.h"
  7. #include "state.h"
  8. #include "settings.h"
  9. #include "resource.h"
  10. #include "main.h"
  11. #include "msx.h"
  12. #include "tool.h"
  13. #include "reverse.h"
  14. #include "sound.h"
  15.  
  16. /*
  17.  
  18. Mostly tested on my MSX1s:
  19. - Canon V-20 VDP: TMS9929ANL (unsynced crystals)
  20. - Panasonic CF2700, VDP under a heatsink, very likely to be a TMS9129
  21. - National (Panasonic) CF1200 (Japanese, NTSC), VDP: TMS9918A
  22. - Sony HB-10P: T6950 (unsynced crystals)
  23. and smaller tests on other people's MSXes
  24.  
  25. Known models on MSXes:
  26. - Texas Instruments TMS9918A/TMS9928A/TMS9929A -- 8/9=60Hz/50Hz, 1/2=YIQ/YPbPr
  27. - Texas Instruments TMS9118/TMS9128/TMS9129 -- support for 4KB was removed
  28. - Toshiba T6950 -- 50Hz/60Hz VDP clone with 42 pins (normal one has 40 pins), one of the extra pins selects PAL/NTSC.
  29.   Support for overlay (video-in) was removed. Used in Sony HB-10P, Toshiba HX-20, Toshiba HX-30, Casio MX-15, ..
  30. - Toshiba T7937A -- VDP inside this MSX engine used in some 60Hz MSX1 (eg. Gradiente), same as T6950? -- not tested well yet, it *does* support M3 table masks
  31. - Yamaha V9938/V9958, used in >=MSX2, designed by ASCII, V9938 also used in some MSX1 (Spectravideo SVI-738, Yamaha CX5M-128)
  32.  
  33. Palettes (colours) may be different due to VDP and/or other circuitry, especially on the T6950.
  34. The evolutions by Yamaha use RGB.
  35.  
  36. Known differences with quirks:
  37. type        4K/16K garble       M3 table masks      M3 pglow mask       M3 sprite clones      M3 mixed mode      M1 bogus mode
  38. TMS99xxA    yes                 yes                 yes                 yes                   yes                yes
  39. TMS91xx     no                  yes                 no                  yes                   yes                yes
  40. T6950       no                  no                  no                  no                    yes                yes
  41. T7937A      ?                   yes                 ?                   ?                     ?                  ?
  42. V99x8       no                  yes                 no                  no                    no                 no              (may have statusregister differences too)
  43.  
  44. Not counting VRAM write timing or vblank length, software that doesn't (ab)use the quirks,
  45. should work on all models. Common MSX1 VDP models are emulated here with scanline accuracy.
  46.  
  47. Unclear:
  48. - pixel-accurate timing and mid-screen VRAM accesses by the Z80
  49. - logical explanation on why sprite cloning behaves the way it does
  50. - mid-screen statusregister reads, especially in screen 0 and blank
  51.  
  52. */
  53.  
  54. static int vdp_chiptype=0;
  55. static int viewbg;
  56. static int viewspr;
  57. static int unlim;       /* will cause glitches in games that use overflow to hide sprite lines (eg. Antarctic Adventure, Athletic Land) */
  58.  
  59. static u8 ram[0x4000];
  60. static int vblank=FALSE;
  61. static int vblank_suppress=FALSE;
  62. static int last_vram_access=0;
  63.  
  64. #define UPLOAD_MAX 0x100
  65. static int upload_pending=FALSE;
  66. static int upload_count=0;
  67. static int upload_address[UPLOAD_MAX];
  68. static int upload_size[UPLOAD_MAX];
  69. static u8* upload_data[UPLOAD_MAX];
  70.  
  71. /* lumi noise */
  72. static void vdp_luminoise_recalc(void);
  73. static void vdp_luminoise_end_frame(void);
  74. static int luminoise=0;
  75. static int lumivol=100; /* in percent */
  76.  
  77. /* regs */
  78. static int regs[8];     /* 8 control registers */
  79. static int bgc=0;       /* bg colour at vblank */
  80. static int status=0;    /* status register */
  81. static int statuslow=0;
  82.  
  83. static int latch=0;     /* 1st/2nd write */
  84. static int address=0;
  85. static int read=0;      /* read ahead buffer */
  86.  
  87. static const char* vdp_chiptype_name[VDP_CHIPTYPE_MAX]={
  88. /*  NTSC                    PAL */
  89.     "TI TMS9118",           "TI TMS9129",
  90.     "TI TMS9918A",          "TI TMS9929A",
  91.     "Toshiba T6950 (60Hz)", "Toshiba T6950 (50Hz)"
  92. };
  93. static const int vdp_chiptype_uid[VDP_CHIPTYPE_MAX]={ 0, 1, 2, 3, 4, 5 };
  94.  
  95. const char* vdp_get_chiptype_name(u32 i) { if (i>=VDP_CHIPTYPE_MAX) return NULL; else return vdp_chiptype_name[i]; }
  96. int __fastcall vdp_get_chiptype(void) { return vdp_chiptype; }
  97. void vdp_set_chiptype(u32 i) { if (i>=VDP_CHIPTYPE_MAX) i=0; vdp_chiptype=i; vdp_luminoise_recalc(); }
  98. void vdp_set_chiptype_vf(int i) { vdp_set_chiptype((vdp_chiptype&~1)|(i!=0)); }
  99. int vdp_get_chiptype_vf(int t) { return t&1; }
  100. int vdp_luminoise_get(void) { return luminoise; }
  101. int vdp_luminoise_get_volume(void) { return lumivol; }
  102.  
  103. int vdp_get_chiptype_uid(u32 type)
  104. {
  105.     if (type>=VDP_CHIPTYPE_MAX) type=0;
  106.     return vdp_chiptype_uid[type];
  107. }
  108.  
  109. int vdp_get_uid_chiptype(u32 id)
  110. {
  111.     int type;
  112.    
  113.     for (type=0;type<VDP_CHIPTYPE_MAX;type++) {
  114.         if (vdp_chiptype_uid[type]==id) return type;
  115.     }
  116.    
  117.     return 0;
  118. }
  119.  
  120. int __fastcall vdp_get_address(void) { return address; }
  121. int __fastcall vdp_get_reg(u32 r) { return regs[r&7]; }
  122. int __fastcall vdp_get_status(void) { return status; }
  123. int __fastcall vdp_get_statuslow(void) { return statuslow; }
  124. u8* __fastcall vdp_get_ram(void) { return ram; }
  125. void __fastcall vdp_reset_vblank(void) { vblank=FALSE; }
  126.  
  127. int vdp_get_bgc(void) { return bgc; }
  128. void vdp_set_bgc(int c) { bgc=c; }
  129. int vdp_get_bg_enabled(void) { return viewbg==0; }
  130. void vdp_set_bg_enabled(int i) { main_menu_check(IDM_LAYERB,i); viewbg=i?0:8; }
  131. int vdp_get_spr_enabled(void) { return viewspr!=0; }
  132. void vdp_set_spr_enabled(int i) { main_menu_check(IDM_LAYERS,i); viewspr=i?0xff:0; }
  133. int vdp_get_spr_unlim(void) { return unlim; }
  134. void vdp_set_spr_unlim(int i) { main_menu_check(IDM_LAYERUNL,i); unlim=i; }
  135.  
  136. /* debug related */
  137. void __fastcall vdp_whereami(char* d)
  138. {
  139.     int i;
  140.     int c=*z80_get_cycles_ptr();
  141.     char s[0x10];
  142.    
  143.     if (c<0) c+=crystal->frame;
  144.    
  145.     for (i=0;i<crystal->lines;i++) {
  146.         if (c<=crystal->sc[i]&&c>=crystal->sc[i+1]) {
  147.             sprintf(s,"%03d,%06.2f",i,((crystal->sc[i]-c)/(float)crystal->vdp_scanline)*342.0);
  148.             break;
  149.         }
  150.     }
  151.    
  152.     if (i==crystal->lines) sprintf(s,"???,???.??");
  153.    
  154.     if (d) strcpy(d,s);
  155.     else printf("%s\n",s);
  156. }
  157.  
  158. void __fastcall vdp_z80toofastvram(void)
  159. {
  160.     int c=z80_get_rel_cycles();
  161.     int pc=z80_get_pc();
  162.    
  163.     if ((last_vram_access-c)<(29*crystal->cycle)/*&&pc!=0x6800&&pc!=0x6846*/) {
  164.         printf("vdpa PC $%04X, cc %02d, ",pc,(last_vram_access-c)/crystal->cycle);
  165.         vdp_whereami(NULL);
  166.     }
  167.    
  168.     if (!vblank&&regs[1]&0x40) last_vram_access=c;
  169. }
  170.  
  171.  
  172. void vdp_init(void)
  173. {
  174.     char* c=NULL;
  175.     int i=8; while (i--) regs[i]=0;
  176.     for (i=0;i<UPLOAD_MAX;i++) upload_data[i]=NULL;
  177.    
  178.     i=settings_get_yesnoauto(SETTINGS_LAYERB);      if (i!=FALSE&&i!=TRUE) i=TRUE;  vdp_set_bg_enabled(i);
  179.     i=settings_get_yesnoauto(SETTINGS_LAYERS);      if (i!=FALSE&&i!=TRUE) i=TRUE;  vdp_set_spr_enabled(i);
  180.     i=settings_get_yesnoauto(SETTINGS_LAYERUNL);    if (i!=FALSE&&i!=TRUE) i=FALSE; vdp_set_spr_unlim(i);
  181.     i=settings_get_yesnoauto(SETTINGS_LUMINOISE);   if (i!=FALSE&&i!=TRUE) i=FALSE; luminoise=i;
  182.    
  183.     if (SETTINGS_GET_INT(settings_info(SETTINGS_LUMINOISE_VOLUME),&i)) { CLAMP(i,0,5000); lumivol=i; }
  184.    
  185.     i=VDP_CHIPTYPE_DEFAULT;
  186.     SETTINGS_GET_STRING(settings_info(SETTINGS_VDPCHIP),&c);
  187.     if (c&&strlen(c)) {
  188.         for (i=0;i<VDP_CHIPTYPE_MAX;i++) if (stricmp(c,vdp_get_chiptype_name(i))==0) break;
  189.         if (i==VDP_CHIPTYPE_MAX) i=VDP_CHIPTYPE_DEFAULT;
  190.     }
  191.     MEM_CLEAN(c);
  192.     vdp_set_chiptype(i);
  193. }
  194.  
  195. void vdp_clean(void)
  196. {
  197.     int i;
  198.     for (i=0;i<UPLOAD_MAX;i++) { MEM_CLEAN(upload_data[i]); }
  199. }
  200.  
  201. void vdp_poweron(void)
  202. {
  203.     int i=8;
  204.     while (i--) regs[i]=0;
  205.     status=statuslow=latch=address=read=last_vram_access=0;
  206.    
  207.     /* power-on VRAM contents: $ff on even and 0 on uneven address on my MSX1s, $ff on my MSX2 */
  208.     /* MSX software known to be affected:
  209.         Universe: Unknown (final) (expects 0, small glitch on stage start otherwise)
  210.     */
  211.     i=0x4000;
  212.     while (i--) ram[i]=(i&1)?0:0xff;
  213. }
  214.  
  215. void vdp_reset(void)
  216. {
  217.     regs[0]=regs[1]=0;
  218.     status=statuslow;
  219. }
  220.  
  221. int vdp_upload(u32 a,u8* data,u32 size)
  222. {
  223.     if ((a&(VDP_UPLOAD_REG-1))>0x3fff||data==NULL||size==0||(a&VDP_UPLOAD_REG&&size!=1)||size>(0x4000-a)||upload_pending&2) return FALSE;
  224.    
  225.     if (msx_get_paused()) {
  226.         /* only copy/invalidate when it differs */
  227.         if (a&VDP_UPLOAD_REG) {
  228.             /* reg */
  229.             if (data[0]!=regs[a&7]) {
  230.                 regs[a&7]=data[0];
  231.                 tool_copy_locals(); reverse_invalidate();
  232.             }
  233.         }
  234.         else if (memcmp(ram+a,data,size)) {
  235.             /* ram */
  236.             memcpy(ram+a,data,size);
  237.             tool_copy_locals(); reverse_invalidate();
  238.         }
  239.     }
  240.     else {
  241.         if (upload_count==UPLOAD_MAX) return FALSE;
  242.        
  243.         upload_pending|=1;
  244.         MEM_CREATE_N(upload_data[upload_count],size);
  245.         memcpy(upload_data[upload_count],data,size);
  246.         upload_size[upload_count]=size;
  247.         upload_address[upload_count]=a;
  248.         upload_count++;
  249.     }
  250.    
  251.     return TRUE;
  252. }
  253.  
  254. void vdp_new_frame(void)
  255. {
  256.     /* upload data */
  257.     if (upload_pending) {
  258.         int i;
  259.         int c=FALSE;
  260.        
  261.         upload_pending|=2;
  262.        
  263.         for (i=0;i<UPLOAD_MAX;i++) {
  264.             if (upload_data[i]==NULL) break;
  265.            
  266.             if (upload_address[i]&VDP_UPLOAD_REG) {
  267.                 /* reg */
  268.                 if (upload_data[i][0]!=regs[upload_address[i]&7]) {
  269.                     regs[upload_address[i]&7]=upload_data[i][0];
  270.                     c=TRUE;
  271.                 }
  272.             }
  273.             else if (memcmp(ram+upload_address[i],upload_data[i],upload_size[i])) {
  274.                 /* ram */
  275.                 memcpy(ram+upload_address[i],upload_data[i],upload_size[i]);
  276.                 c=TRUE;
  277.             }
  278.            
  279.             MEM_CLEAN(upload_data[i]);
  280.         }
  281.        
  282.         if (c) reverse_invalidate();
  283.         upload_count=0;
  284.         upload_pending=FALSE;
  285.     }
  286.    
  287.     vblank=FALSE;
  288.    
  289.     if (last_vram_access<(2*crystal->frame)) last_vram_access+=crystal->frame;
  290. }
  291.  
  292. void vdp_end_frame(void)
  293. {
  294.     vdp_luminoise_end_frame();
  295. }
  296.  
  297. void __fastcall vdp_vblank(void)
  298. {
  299.     if (vblank) return;
  300.    
  301.     vblank=TRUE;
  302.     bgc=regs[7]&0xf; /* remember background colour */
  303.    
  304.     if (!vblank_suppress) {
  305.         status|=0x80;
  306.         if (regs[1]&0x20) z80_irq_next(2*crystal->frame);
  307.     }
  308.     else vblank_suppress=FALSE;
  309. }
  310.  
  311.  
  312. /* data read */
  313. u8 __fastcall vdp_read_data(void)
  314. {
  315.     u8 ret=read;
  316.     read=ram[address];
  317.     address=(address+1)&0x3fff;
  318.     latch=0;
  319. #if VDP_FASTACCESS
  320.     vdp_z80toofastvram();
  321. #endif
  322.     return ret;
  323. }
  324.  
  325. /* data write */
  326. void __fastcall vdp_write_data(u8 v)
  327. {
  328.     read=ram[address]=v;
  329.     address=(address+1)&0x3fff;
  330.     latch=0;
  331. #if VDP_FASTACCESS
  332.     vdp_z80toofastvram();
  333. #endif
  334. }
  335.  
  336. /* address/reg write */
  337. void __fastcall vdp_write_address(u8 v)
  338. {
  339.     if (latch) {
  340.         address=(v<<8|(address&0xff))&0x3fff;
  341.        
  342.         /* reg */
  343.         if (v&0x80) {
  344.            
  345.             /* EXTVID (register 0 bit 0): causes static/sync problems on my MSX1s, not emulatable */
  346.             /* if (!(v&7)&&address&1) printf("X"); */
  347.            
  348.             /* reg 1 special cases */
  349.             if ((v&7)==1) {
  350.                
  351.                 /* interrupt */
  352.                 if (status&0x80) {
  353.                     if (address&0x20) { if (!z80_irq_pending()) z80_irq_next(z80_get_cycles()); }
  354.                     else if (z80_irq_pending()) z80_irq_ack();
  355.                 }
  356.                
  357.                 /* 4K/16K mode swaps addresslines on TMS99xxA. */
  358.                 /* On (most?) real chips, unmapped RAM in 4K mode will degrade in time to its
  359.                 initial power-on contents (maybe faster with heat), this effect is unemulated. */
  360.                 if ((regs[1]^address)&0x80&&(vdp_chiptype&~1)==VDP_CHIPTYPE_TMS9918) {
  361.                     u8 buf[0x4000];
  362.                     int i=0x4000;
  363.                    
  364.                     if (address&0x80) while (i--) buf[i]=ram[(i&0x203f)|(i>>1&0xfc0)|(i<<6&0x1000)];
  365.                     else while (i--) buf[i]=ram[(i&0x203f)|(i<<1&0x1f80)|(i>>6&0x40)];
  366.                    
  367.                     memcpy(ram,buf,0x4000);
  368.                 }
  369.             }
  370.            
  371.             regs[v&7]=address&0xff;
  372.         }
  373.        
  374.         /* read */
  375.         else if (~v&0x40) {
  376.             read=ram[address];
  377.             address=(address+1)&0x3fff;
  378. #if VDP_FASTACCESS
  379.             vdp_z80toofastvram();
  380. #endif
  381.         }
  382.     }
  383.     else address=(address&0x3f00)|v;
  384.    
  385.     latch^=1;
  386. }
  387.  
  388. /* status read */
  389. u8 __fastcall vdp_read_status(void)
  390. {
  391.     int cc;
  392.    
  393.     /* in reality, the lower bits are filled with the internal horizontal/sprite counter */
  394.     u8 ret=status;
  395.     latch=0;
  396.     status=statuslow;
  397.    
  398.     /* If the status register is read just before vblank, vblank interrupt is suppressed and vblank status is not set
  399.     (or cleared at the same time it's read+set). If it's read exactly at vblank, only the interrupt is suppressed */
  400.     if (!vblank&&(cc=*z80_get_cycles_ptr())>=crystal->vblank_trigger&&cc<(crystal->vblank_trigger+3*crystal->vdp_cycle)) {
  401.         if (cc<(crystal->vblank_trigger+crystal->vdp_cycle)) ret|=0x80;
  402.         vblank_suppress=TRUE;
  403.     }
  404.    
  405.     if (z80_irq_pending()) z80_irq_ack();
  406.     return ret;
  407. }
  408.  
  409.  
  410. /* render 1 scanline */
  411. void __fastcall vdp_line(int line)
  412. {
  413.     u8* screen=draw_get_screen_ptr()+256*line;
  414.     int mode=(regs[1]>>4&1)|(regs[1]>>1&4)|(regs[0]&2)|viewbg; /* bit 0: M1, bit 1: M3, bit 2: M2, bit 3: bg disabled */
  415.     int pn=regs[2]<<10&0x3fff;  /* pattern nametable */
  416.     int pg=regs[4]<<11&0x3fff;  /* pattern generator table */
  417.     int ct=regs[3]<<6;          /* colour table */
  418.     int bd=regs[7]&0xf;         /* background colour */
  419.     int pg_mask=0x3fff,ct_mask=0x3fff;
  420.     const int is_99xx=(vdp_chiptype&~1)==VDP_CHIPTYPE_TMS9918;
  421.     const int is_toshiba=(vdp_chiptype&~1)==VDP_CHIPTYPE_T6950_NTSC;
  422.    
  423.     /* Example software using M3 pg/ct mirroring:
  424.     - Can of Worms (some of the minigames)
  425.     - Ice King
  426.    
  427.     - demos by L!T/Bandwagon
  428.     - Dr. Archie (sprite cloning of the boat in the intro happens on real MSX too)
  429.     - Lotus F3 (with MSX1 non-reduced palette, + causes sprite clones)
  430.     - Moon Over Arba Minch (game in development)
  431.     - Universe: Unknown (intro, not in-game)
  432.    
  433.     undocumented "mixed" screenmodes aren't used often, just in dvik/joyrex's "scr5.rom" and Illusions demo */
  434.     if (~regs[1]&0x40) { mode=9; statuslow=0x1f; } /* blank screen */
  435.     else if (mode&2) {
  436.         if (is_toshiba) { pg|=0x1800; ct|=0x1fc0; } /* no M3 pg/ct mirroring on Toshiba VDPs */
  437.         pg=(line<<5&pg)|(pg&0x2000);
  438.         ct_mask=ct|0x3f;
  439.         if (is_99xx) pg_mask=0x3800|ct_mask; /* additional pg mirroring on 99xx VDPs */
  440.        
  441.         /* M3 combination */
  442.         if (mode&5) mode^=2;
  443.     }
  444.    
  445.     switch (mode) {
  446.        
  447.         /* screen 1 */
  448.         case 0: {
  449.             int x,pd,p,cd;
  450.            
  451.             pn|=(line<<2&0xfe0);
  452.             pg|=(line&7);
  453.            
  454.             /* 32 tiles, 8 pixels per tile */
  455.             for (x=0;x<32;x++) {
  456.                 cd=ram[pn|x];
  457.                 pd=ram[cd<<3|pg];
  458.                 cd=ram[cd>>3|ct];
  459.                
  460.                 #define UPD1() *screen++=(p=((pd<<=1)&0x100)?cd>>4:cd&0xf)?p:bd
  461.                 UPD1(); UPD1(); UPD1(); UPD1(); UPD1(); UPD1(); UPD1(); UPD1();
  462.                 /* (screen 2 uses it too) */
  463.             }
  464.            
  465.             break;
  466.         }
  467.        
  468.         /* screen 0 */
  469.         case 1: case 5: {
  470.             int x,tc=regs[7]>>4;
  471.             if (!tc) tc=bd;
  472.            
  473.             /* left border, 6 pixels (9 on MSX2 and up) */
  474.             *screen++=bd; *screen++=bd; *screen++=bd; *screen++=bd;
  475.             *screen++=bd; *screen++=bd;
  476.            
  477.             if (mode&4) {
  478.                 /* bogus mode: M2 (or +3) is set too, this causes a glitched,
  479.                 but consistent static screen with vertical bars, unaffected by
  480.                 VRAM contents */
  481.                
  482.                 /* 40 times 4 pixels text colour, 2 pixels background colour */
  483.                 for (x=0;x<40;x++) {
  484.                     *screen++=tc; *screen++=tc; *screen++=tc; *screen++=tc;
  485.                     *screen++=bd; *screen++=bd;
  486.                 }
  487.             }
  488.             else {
  489.                 /* standard M1 */
  490.                 int pd;
  491.                
  492.                 pn|=((line>>3)*40);
  493.                 pg|=(line&7);
  494.                
  495.                 /* 40 tiles, 6 pixels per tile */
  496.                 for (x=0;x<40;x++) {
  497.                     pd=ram[(ram[pn+x]<<3|pg)&pg_mask];
  498.                    
  499.                     #define UPD0() *screen++=((pd<<=1)&0x100)?tc:bd;
  500.                     UPD0(); UPD0(); UPD0(); UPD0(); UPD0(); UPD0();
  501.                     #undef UPD0
  502.                 }
  503.             }
  504.            
  505.             /* right border, 10 pixels (7 on MSX2 and up) */
  506.             *screen++=bd; *screen++=bd; *screen++=bd; *screen++=bd;
  507.             *screen++=bd; *screen++=bd; *screen++=bd; *screen++=bd;
  508.             *screen++=bd; *screen++=bd;
  509.            
  510.             statuslow=0x1f;
  511.            
  512.             break;
  513.         }
  514.        
  515.         /* screen 2, M3 aka high res */
  516.         case 2: {
  517.             int x,pd,p,cd;
  518.            
  519.             pn|=(line<<2&0xfe0);
  520.             pg|=(line&7);
  521.             ct=(ct&0x2000)|(line&7)|(line<<5&0x1800);
  522.            
  523.             /* 32 tiles, 8 pixels per tile */
  524.             for (x=0;x<32;x++) {
  525.                 cd=ram[pn|x]<<3;
  526.                 pd=ram[(cd|pg)&pg_mask];
  527.                 cd=ram[(cd|ct)&ct_mask];
  528.                
  529.                 UPD1(); UPD1(); UPD1(); UPD1(); UPD1(); UPD1(); UPD1(); UPD1();
  530.                 #undef UPD1
  531.             }
  532.            
  533.             break;
  534.         }
  535.        
  536.         /* screen 3, M2 aka multicolor */
  537.         case 4: {
  538.             int x,pd,p;
  539.            
  540.             pn|=(line<<2&0xfe0);
  541.             pg|=(line>>2&7);
  542.            
  543.             /* 32 tiles, 8 pixels per 'tile' */
  544.             for (x=0;x<32;x++) {
  545.                 pd=ram[(ram[pn|x]<<3|pg)&pg_mask];
  546.                
  547.                 /* left 4 pixels */
  548.                 p=pd>>4; p=p?p:bd;
  549.                 *screen++=p; *screen++=p; *screen++=p; *screen++=p;
  550.                
  551.                 /* right 4 pixels */
  552.                 p=pd&0xf; p=p?p:bd;
  553.                 *screen++=p; *screen++=p; *screen++=p; *screen++=p;
  554.             }
  555.            
  556.             break;
  557.         }
  558.        
  559.         /* blank screen */
  560.         default: {
  561.             memset(screen,bd,256);
  562.             screen+=256;
  563.            
  564.             break;
  565.         }
  566.     }
  567.    
  568.     /* sprites */
  569.     if (~mode&1) {
  570.         int size=8<<(regs[1]>>1&1),mag=regs[1]&1;
  571.         int smax=(size<<mag)-1;
  572.         int smask=(size&16)?0xfe0:0xfff;
  573.         int y,f=0,o=0x20,clone=0x20,slmask=0xff;
  574.         int clonemask[6]={0xff,0,0,0xff,0,0};   /* line AND, y XOR, y OR */
  575.         u8* sa=ram+(regs[5]<<7&0x3fff);         /* sprite attribute table */
  576.         u8* sg=ram+(regs[6]<<11&0x3fff);        /* sprite generator table */
  577.         u8 sl[0x20+0x100+0x20];                 /* sprite line */
  578.         u8 yc;
  579.        
  580.         statuslow=0;
  581.        
  582.         line=(line-1)&0xff; /* sprite preprocessing is actually done one line in advance */
  583.        
  584.         /* invalidate out of bounds area */
  585.         memset(sl,0x80,0x20);
  586.         memset(sl+0x20,0,0x100);
  587.         memset(sl+0x120,0x80,0x20);
  588.        
  589.         /* init sprite cloning */
  590.         if (regs[0]&2&&(regs[4]&3)!=3&&!is_toshiba) {
  591.             /* On TMS9xxx(/A) M3, sprites 8-31 Y position(s) is influenced by the least two
  592.             bits of the pattern generator table offset, and somewhat by bits 5 and 6 of the
  593.             colour table register. Sprite locations, mostly those on Y 0-63, will become
  594.             glitchy, and cause a cloning effect similar to tiles with M3 table mirroring.
  595.             This is not just a visual effect, as sprite collision and overflow behave as if
  596.             sprites are normal. If the VDP is running hot, this effect will deteriorate
  597.             (confirmed by flyguille with a blow dryer :) ), starting with block 1, and
  598.             block 2 shortly after (effect deterioration from heat is unemulated). I assume
  599.             the reason for the first 8 sprites not being affected is due to them being
  600.             preprocessed in hblank. This glitch is briefly mentioned in the official
  601.             TMS91xx programming manual btw, meaning that it's not undocumented.
  602.            
  603.             Known software affected by this (not counting tests or small glitches):
  604.             - Alankomaat by Bandwagon, at the fire part (intended)
  605.             - Lotus F3, unintended problems in MSX1 palette mode (black screen on my MSX1s)
  606.            
  607.             The calculations below are done to get the correct result, I can't think of
  608.             a way to solve this logically. This implementation has been tested side by side
  609.             to my MSX1, with all possible sprite Y and addressmasks. */
  610.            
  611.             /* 0-255, 4 blocks of 64 lines */
  612.             if (line>191) {
  613.                 /* block 3 (only visible at the far top of the screen)
  614.                 Sprites are cloned from block borders. The colour block
  615.                 erase effect is the same as on block 2 below. */
  616.                 clonemask[0]=0xff; clonemask[2]=~regs[4]<<6&0xc0;
  617.                 if (~regs[3]&0x40&&clonemask[2]&0x80) {
  618.                     clonemask[0]&=0x7f;
  619.                     clonemask[2]&=0x7f;
  620.                 }
  621.                
  622.                 clonemask[3]=clonemask[0]; clonemask[5]=clonemask[2];
  623.                
  624.                 clone=7;
  625.             }
  626.             else if (line>127) {
  627.                 /* block 2, sprites are cloned from block 0.
  628.                 The bottom part of sprites on block 1+2 is always
  629.                 invisible. If this colour block mask is reset, real
  630.                 sprites in block 2 will be erased. */
  631.                
  632.                 /* only has effect if this pattern block mask is reset */
  633.                 if (~regs[4]&2) {
  634.                     clonemask[1]=clonemask[4]=0x80;
  635.                     clonemask[5]=regs[3]<<1&0x80;
  636.                    
  637.                     clone=7;
  638.                 }
  639.             }
  640.             else if (line>63) {
  641.                 /* block 1, sprites are cloned from block 0.
  642.                 If this colour block mask is reset, the bottom part of
  643.                 sprites on block 0+1 will be invisible. */
  644.                
  645.                 /* only has effect if this pattern block mask is reset */
  646.                 if (~regs[4]&1) {
  647.                     clonemask[0]=0x3f;
  648.                     clonemask[5]=~regs[3]<<1&0x40;
  649.                    
  650.                     clone=7;
  651.                 }
  652.             }
  653.             else {
  654.                 /* block 0, no effect */
  655.                 ;
  656.             }
  657.         }
  658.        
  659.         for (;;) {
  660.             /* forced break */
  661.             if ((y=*sa++)==208) break;
  662.            
  663.             /* calculate offset */
  664.             if (statuslow>clone) {
  665.                 yc=(line&clonemask[0])-((y^clonemask[1])|clonemask[2]);
  666.                 if (yc>smax) yc=(line&clonemask[3])-((y^clonemask[4])|clonemask[5]);
  667.             }
  668.             else yc=line-y;
  669.            
  670.             /* found sprite */
  671.             if (yc<=smax) {
  672.                 u8* slp; int cd,g,x=*sa+++32;
  673.                 int pd=sg[g=yc>>mag|(*sa++<<3&smask)];          /* pixel data */
  674.                 if (f++&4) {
  675.                     o|=((status>>1^0x40)&0x40);                 /* overflow */
  676.                     if (unlim) {                                /* unlimited sprites? continue */
  677.                         if (slmask&0x80) { o&=0x40; slmask=statuslow; }
  678.                     }
  679.                     else break;
  680.                 }
  681.                 if ((cd=*sa++)&0x80) x-=32; cd=(cd&0xf)|0x20;   /* colour data */
  682.                
  683.                 slp=sl+x;
  684.                
  685.                 /* normal 8 pixel update */
  686.                 #define UPDS()                                  \
  687.                 if ((pd<<=1)&0x100) {                           \
  688.                     status|=(*slp&0x20&o); /* collision */      \
  689.                     if (!(*slp&0x8f)) *slp=cd;                  \
  690.                 } slp++
  691.                
  692.                 /* magnified (16 pixels) update */
  693.                 #define UPDSM()                                 \
  694.                 if ((pd<<=1)&0x100) {                           \
  695.                     status|=((*slp|(*slp+1))&0x20&o);           \
  696.                     if (!(*slp&0x8f)) *slp=cd; slp++;           \
  697.                     if (!(*slp&0x8f)) *slp=cd; slp++;           \
  698.                 } else slp+=2
  699.                
  700.                 if (mag) { UPDSM(); UPDSM(); UPDSM(); UPDSM(); UPDSM(); UPDSM(); UPDSM(); UPDSM(); }
  701.                 else { UPDS(); UPDS(); UPDS(); UPDS(); UPDS(); UPDS(); UPDS(); UPDS(); }
  702.                
  703.                 /* 16*16 */
  704.                 if (size&16) {
  705.                     pd=sg[g|16];
  706.                    
  707.                     if (mag) { UPDSM(); UPDSM(); UPDSM(); UPDSM(); UPDSM(); UPDSM(); UPDSM(); UPDSM(); }
  708.                     else { UPDS(); UPDS(); UPDS(); UPDS(); UPDS(); UPDS(); UPDS(); UPDS(); }
  709.                 }
  710.                
  711.                 #undef UPDS
  712.                 #undef UPDSM
  713.             }
  714.             else sa+=3;
  715.            
  716.             /* all sprites checked */
  717.             if (statuslow==31) break;
  718.             else statuslow++;
  719.         }
  720.        
  721.         statuslow&=slmask;
  722.         if (~status&0x40) status=(status&0xe0)|statuslow|(o&0x40);
  723.        
  724.         /* update screen */
  725.         if (f&viewspr) {
  726.             int x=256; u8* slp=sl+32;
  727.             screen-=256;
  728.            
  729.             while (x--) {
  730.                 if (*slp&0xf) *screen=*slp&0xf;
  731.                 screen++; slp++;
  732.             }
  733.         }
  734.     }
  735. }
  736.  
  737.  
  738. /* lumi noise */
  739. /* simulation of VDP brightness changes interference on the MSX audio line, basically
  740. PCM with a range of 5.4MHz, it's pretty accurate, except that (most?) tvs seem to
  741. have a highpass filter, diminishing the 50/60Hz hum */
  742. #define LUMI_VOLUME     600.0
  743.  
  744. static int* luminoise_dac=NULL;
  745.  
  746. #define O_LUMI_BLANK    16
  747. #define O_LUMI_SYNC     17
  748. #define O_LUMI_MAX      18
  749.  
  750. static int lut_lumi[O_LUMI_MAX];
  751.  
  752. /* known types luminance */
  753. static const float lut_lumi_t[][O_LUMI_MAX]={
  754. /*                0     1     2     3     4     5     6     7     8     9     A     B     C     D     E     F      blank  sync */
  755. /* 9x18      */ { 0.00, 0.00, 0.53, 0.67, 0.40, 0.53, 0.47, 0.67, 0.53, 0.67, 0.73, 0.80, 0.46, 0.53, 0.80, 1.00,  0.00,  -0.40 },
  756. /* 9x28/9929 */ { 0.00, 0.00, 0.53, 0.67, 0.40, 0.53, 0.47, 0.73, 0.53, 0.67, 0.73, 0.80, 0.47, 0.53, 0.80, 1.00,  0.00,  -0.46 },
  757. /* 9129      */ { 0.00, 0.00, 0.60, 0.73, 0.47, 0.60, 0.53, 0.73, 0.60, 0.73, 0.77, 0.83, 0.53, 0.60, 0.80, 1.00,  0.00,  -0.43 }
  758. };
  759.  
  760. void vdp_luminoise_set(int l)
  761. {
  762.     if (!msx_is_running()||l==luminoise) return;
  763.    
  764.     luminoise=l;
  765.    
  766.     main_menu_check(IDM_LUMINOISE,l);
  767.     if (l) luminoise_dac=sound_create_dac();
  768.     else sound_clean_dac(luminoise_dac);
  769. }
  770.  
  771. static void vdp_luminoise_recalc(void)
  772. {
  773.     float f,min=0,max=0;
  774.     int i,t=2;
  775.    
  776.     switch (vdp_chiptype) {
  777.         case VDP_CHIPTYPE_TMS9118:    t=0; break;
  778.         case VDP_CHIPTYPE_TMS9129:    t=2; break;
  779.         case VDP_CHIPTYPE_TMS9918:    t=0; break;
  780.         case VDP_CHIPTYPE_TMS9929:    t=1; break;
  781.         case VDP_CHIPTYPE_T6950_NTSC: t=1; break;
  782.         case VDP_CHIPTYPE_T6950_PAL:  t=1; break;
  783.         default: break;
  784.     }
  785.    
  786.     /* init normalisation (knowing that min<0) */
  787.     for (i=0;i<O_LUMI_MAX;i++) {
  788.         f=lut_lumi_t[t][i];
  789.         if (f<min) min=f;
  790.         if (f>max) max=f;
  791.     }
  792.     max-=min;
  793.    
  794.     /* fill lut */
  795.     for (i=0;i<O_LUMI_MAX;i++) {
  796.         f=lut_lumi_t[t][i]+min;
  797.         if (f<0) f=0;
  798.         lut_lumi[i]=(f/max)*LUMI_VOLUME*(lumivol/100.0);
  799.     }
  800. }
  801.  
  802. static void vdp_luminoise_end_frame(void)
  803. {
  804.     int b,c,d,i,j;
  805.     u8* screen;
  806.     int* dac=luminoise_dac;
  807.    
  808.     if (!luminoise||!sound_get_enabled()) return;
  809.    
  810.     screen=draw_get_screen_ptr();
  811.    
  812.     /* hblank shortcut (56 z80 clocks) */
  813.     #define L_HBLANK()                                                                          \
  814.         c=lut_lumi[b];            j=8;  while (j--) *dac++=c; /* right border */                \
  815.         c=lut_lumi[O_LUMI_BLANK]; j=6;  while (j--) *dac++=c; /* right blanking */              \
  816.         c=lut_lumi[O_LUMI_SYNC];  j=18; while (j--) *dac++=c; /* horizontal sync */             \
  817.         c=lut_lumi[O_LUMI_BLANK]; j=16; while (j--) *dac++=c; /* left blanking + color burst */ \
  818.         c=lut_lumi[b];            j=8;  while (j--) *dac++=c  /* left border */
  819.    
  820.     /* vblank shortcut (172 z80 clocks) */
  821.     #define L_VBLANK(x,y)                                                                       \
  822.         b=x; d=lut_lumi[b]; i=y;                                                                \
  823.         while (i--) {                                                                           \
  824.             j=172; while (j--) *dac++=d;                                                        \
  825.             L_HBLANK();                                                                         \
  826.         }
  827.    
  828.     /* active display */
  829.     b=bgc; i=192;
  830.     while (i--) {
  831.         /* 255 pixels (170 z80 clocks) */
  832.         j=85; while (j--) {
  833.             *dac++=(lut_lumi[*screen]+lut_lumi[*screen]+lut_lumi[*(screen+1)])/3; screen++;
  834.             *dac++=(lut_lumi[*screen]+lut_lumi[*(screen+1)]+lut_lumi[*(screen+1)])/3; screen++;
  835.             screen++;
  836.         }
  837.        
  838.         /* pixel 256 + 2 border pixels (2 z80 clocks) */
  839.         *dac++=(lut_lumi[*screen]+lut_lumi[*screen]+lut_lumi[b])/3; screen++;
  840.         *dac++=lut_lumi[b];
  841.        
  842.         L_HBLANK();
  843.     }
  844.    
  845.     L_VBLANK(bgc,24)                          /* bottom border */
  846.     L_VBLANK(O_LUMI_BLANK,crystal->mode?54:3) /* bottom blanking */
  847.    
  848.     /* vertical sync (should contain a pulse too) */
  849.     c=lut_lumi[O_LUMI_SYNC]; i=3*228;
  850.     while (i--) *dac++=c;
  851.    
  852.     L_VBLANK(O_LUMI_BLANK,13)                 /* top blanking */
  853.     L_VBLANK(bgc,28)                          /* top border (+1 padding) */
  854.    
  855.     #undef L_HBLANK
  856.     #undef L_VBLANK
  857. }
  858.  
  859.  
  860. /* state                size
  861. ram                     0x4000
  862. regs                    8
  863. vblank                  1
  864. bgc                     1
  865. status                  1
  866. statuslow               1
  867. latch                   1
  868. address                 2
  869. read                    1
  870.  
  871. ==                      0x4000+16
  872. */
  873. #define STATE_VERSION   1
  874. #define STATE_SIZE      (0x4000+16)
  875.  
  876. int __fastcall vdp_state_get_version(void)
  877. {
  878.     return STATE_VERSION;
  879. }
  880.  
  881. int __fastcall vdp_state_get_size(void)
  882. {
  883.     return STATE_SIZE;
  884. }
  885.  
  886. /* save */
  887. void __fastcall vdp_state_save(u8** s)
  888. {
  889.     STATE_SAVE_C(ram,0x4000);
  890.    
  891.     STATE_SAVE_1(regs[0]);  STATE_SAVE_1(regs[1]);  STATE_SAVE_1(regs[2]);  STATE_SAVE_1(regs[3]);
  892.     STATE_SAVE_1(regs[4]);  STATE_SAVE_1(regs[5]);  STATE_SAVE_1(regs[6]);  STATE_SAVE_1(regs[7]);
  893.    
  894.     STATE_SAVE_1(vblank);
  895.     STATE_SAVE_1(bgc);
  896.     STATE_SAVE_1(status);   STATE_SAVE_1(statuslow);
  897.     STATE_SAVE_1(latch);
  898.     STATE_SAVE_2(address);
  899.     STATE_SAVE_1(read);
  900. }
  901.  
  902. /* load */
  903. void __fastcall vdp_state_load_cur(u8** s)
  904. {
  905.     STATE_LOAD_C(ram,0x4000);
  906.    
  907.     STATE_LOAD_1(regs[0]);  STATE_LOAD_1(regs[1]);  STATE_LOAD_1(regs[2]);  STATE_LOAD_1(regs[3]);
  908.     STATE_LOAD_1(regs[4]);  STATE_LOAD_1(regs[5]);  STATE_LOAD_1(regs[6]);  STATE_LOAD_1(regs[7]);
  909.    
  910.     STATE_LOAD_1(vblank);
  911.     STATE_LOAD_1(bgc);
  912.     STATE_LOAD_1(status);   STATE_LOAD_1(statuslow);
  913.     STATE_LOAD_1(latch);
  914.     STATE_LOAD_2(address);
  915.     STATE_LOAD_1(read);
  916. }
  917.  
  918. int __fastcall vdp_state_load(int v,u8** s)
  919. {
  920.     switch (v) {
  921.         case STATE_VERSION:
  922.             vdp_state_load_cur(s);
  923.             break;
  924.        
  925.         default: return FALSE;
  926.     }
  927.    
  928.     return TRUE;
  929. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement