home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / programs / emulaton / at2600 / !v2600 / c / vmachine < prev   
Text File  |  1998-04-11  |  14KB  |  675 lines

  1. /*****************************************************************************
  2.  
  3.    This file is part of x2600, the Atari 2600 Emulator
  4.    ===================================================
  5.  
  6.    Copyright 1996 Alex Hornby. For contributions see the file CREDITS.
  7.  
  8.    This software is distributed under the terms of the GNU General Public
  9.    License. This is free software with ABSOLUTELY NO WARRANTY.
  10.  
  11.    See the file COPYING for details.
  12.  
  13.    $Id: vmachine.c,v 2.20 1997/02/23 20:39:29 ahornby Exp $
  14. ******************************************************************************/
  15.  
  16. /*
  17.    The virtual machine. Contains the RIOT timer code, and hardware
  18.    initialisation.
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include "string.h"
  23. #include "types.h"
  24. #include "address.h"
  25. #include "options.h"
  26. #include "display.h"
  27. #include "raster.h"
  28. #include "cpu.h"
  29. #include "collision.h"
  30. #include "sound.h"
  31. #include "control.h"
  32.  
  33. /* The Rom define might need altering for paged carts */
  34. /* Enough for 16k carts */
  35. int rom_size;
  36.  
  37. /* Used as a simple file buffer to store the data */
  38. BYTE theCart[16384];
  39.  
  40. /* Pointer to start of ROM data */
  41. BYTE *theRom;
  42.  
  43. /* Scratch area for those banking types that require memcpy() */
  44. BYTE cartScratch[4096];
  45.  
  46. /* Area for those carts containing RAM */
  47. BYTE cartRam[1024];
  48.  
  49. BYTE theRam[128];
  50. BYTE tiaRead[0x0e];
  51. BYTE tiaWrite[0x2d];
  52. BYTE keypad[2][4];
  53.  
  54. /* These don't strictly need so much space */
  55. BYTE riotRead[0x298];
  56. BYTE riotWrite[0x298];
  57.  
  58. /*
  59.    Hardware addresses not programmer accessible
  60.  */
  61.  
  62. /* Set if whole emulator is reset */
  63. int reset_flag = 0;
  64.  
  65. /* The timer resolution, can be 1,8,64,1024 */
  66. int timer_res = 32;
  67. int timer_count = 0;
  68. int timer_clks = 0;
  69. extern CLOCK clk;
  70. extern int beamadj;
  71.  
  72. /* Electron beam position */
  73. int ebeamx, ebeamy, sbeamx;
  74.  
  75. /* The state of the electron beam */
  76. #define VSYNCSTATE 1
  77. #define VBLANKSTATE 2
  78. #define HSYNCSTATE 4
  79. #define DRAWSTATE 8
  80. #define OVERSTATE 16
  81. int vbeam_state;        /* 1 2 8 or 16 */
  82. int hbeam_state;        /* 4 8 or 16 */
  83.  
  84. /* The tv size, varies with PAL/NTSC */
  85. int tv_width, tv_height, tv_vsync, tv_vblank, tv_overscan, tv_frame, tv_hertz,
  86.   tv_hsync;
  87.  
  88. /* The PlayField structure */
  89. struct PlayField
  90.   {
  91.     BYTE pf0, pf1, pf2, ref;
  92.   }
  93. pf[2];
  94.  
  95. struct Paddle
  96.   {
  97.     int pos;
  98.     int val;
  99.   }
  100. paddle[4];
  101.  
  102. /* The player variables */
  103. struct Player
  104.   {
  105.     int x;
  106.     BYTE grp;
  107.     BYTE hmm;
  108.     BYTE vdel;
  109.     BYTE vdel_flag;
  110.     BYTE nusize;
  111.     BYTE reflect;
  112.     BYTE mask;
  113.   }
  114. pl[2];
  115.  
  116. /* The element used in display lists */
  117. struct RasterChange
  118.   {
  119.     int x;            /* Position at which change happened */
  120.     int type;            /* Type of change */
  121.     int val;            /* Value of change */
  122.   };
  123.  
  124. #define MAXLIST 80
  125. /* The various display lists */
  126. struct RasterChange pl_change[2][MAXLIST], pf_change[1][MAXLIST], unified[MAXLIST];
  127.  
  128. /* The display list counters */
  129. int pl_change_count[2], pf_change_count[1], unified_count;
  130.  
  131. /* The missile an ball positions */
  132. struct Missile
  133.   {
  134.     int x;
  135.     BYTE hmm;
  136.     BYTE enabled;
  137.     BYTE locked;
  138.     BYTE width;
  139.     BYTE vdel;
  140.     BYTE vdel_flag;
  141.     BYTE mask;
  142.   }
  143. ml[3];
  144.  
  145.  
  146.  
  147. /***************************************************************************
  148.                            Let the functions begin!
  149. ****************************************************************************/
  150.  
  151. /* Device independent screen initialisations */
  152. void
  153. init_screen (void)
  154. {
  155.   /* Set the electron beam to the top left */
  156.   ebeamx = -tv_hsync;
  157.   ebeamy = 0;
  158.   vbeam_state = VSYNCSTATE;
  159.   hbeam_state = OVERSTATE;
  160.  
  161.   tv_vsync = 3;
  162.   tv_hsync = 68;
  163.   switch (base_opts.tvtype)
  164.     {
  165.     case NTSC:
  166.       tv_width = 160;
  167.       tv_height = 192;
  168.       tv_vblank = 40;
  169.       tv_overscan = 30;
  170.       tv_frame = 262;
  171.       tv_hertz = 60;
  172.     break;
  173.     case PAL:
  174.     case SECAM:
  175.     default:
  176.       tv_width = 160;
  177.       tv_height = 228;
  178.       tv_vblank = 48;
  179.       tv_overscan = 36;
  180.       tv_frame = 312;
  181.       tv_hertz = 50;
  182.       break;
  183.     }
  184. }
  185.  
  186. /* Initialise the RIOT (also known as PIA) */
  187. void
  188. init_riot (void)
  189. {
  190.   int i;
  191.   /* Wipe the RAM */
  192.   for (i = 0; i < 0x80; i++)
  193.     theRam[i] = 0;
  194.   /* Set the timer to zero */
  195.   riotRead[INTIM] = 0;
  196.   /* Set the joysticks and switches to input */
  197.   riotWrite[SWACNT] = 0;
  198.   riotWrite[SWBCNT] = 0;
  199.  
  200.   /* Centre the joysticks */
  201.   riotRead[SWCHA] = 0xff;
  202.   riotRead[SWCHB] = 0x0b;
  203.  
  204.   /* Set the counter resolution */
  205.   timer_res = 32;
  206.   timer_count = 0;
  207.   timer_clks = 0;
  208. }
  209.  
  210. /* Initialise the television interface adaptor (TIA) */
  211. void
  212. init_tia (void)
  213. {
  214.   int i;
  215.   tiaWrite[CTRLPF] = 0x00;
  216.   for (i = 0; i < 2; i++)
  217.     {
  218.       pl[i].hmm = 0x0;
  219.       pl[i].x = 0x0;
  220.       pl[i].nusize = 0;
  221.       pl[i].grp = 0;
  222.       pl[i].vdel = 0;
  223.       pl[i].vdel_flag = 0;
  224.       pl_change_count[i] = 0;
  225.     }
  226.  
  227.   pl[0].mask = PL0_MASK;
  228.   pl[1].mask = PL1_MASK;
  229.   ml[0].mask = ML0_MASK;
  230.   ml[1].mask = ML1_MASK;
  231.   reset_collisions ();
  232.  
  233.   pf_change_count[0] = 0;
  234.   unified_count = 0;
  235.   for (i = 0; i < 3; i++)
  236.     {
  237.       ml[i].enabled = 0;
  238.     }
  239.  
  240.   tiaWrite[VBLANK] = 0;
  241.   tiaRead[INPT4] = 0x80;
  242.   tiaRead[INPT5] = 0x80;
  243.  
  244.   /* Set up the colour table */
  245.   colour_table[P0M0_COLOUR]=0xf4;
  246.   colour_table[P1M1_COLOUR]=0xf4;
  247.   colour_table[PFBL_COLOUR] = 0xf6;
  248.   colour_table[BK_COLOUR] = 0xf6;
  249. }
  250.  
  251. void
  252. init_memory(void)
  253. {
  254.   int i;
  255.   for(i=0;i<1024; i++)
  256.     cartRam[i]=0;
  257. }
  258.  
  259. void
  260. init_banking (void)
  261. {
  262.   /* Set to the first bank */
  263.   if (rom_size == 2048)
  264.     theRom = &theCart[rom_size - 2048];
  265.   else
  266.     theRom = &theCart[rom_size - 4096];
  267.  
  268.   switch(base_opts.bank)
  269.     {
  270.     case 3:
  271.       /* Parker Brothers 8k E0 */
  272.       memcpy(&cartScratch[0xc00],&theCart[0x1c00],1024);
  273.       memcpy(&cartScratch[0],&theCart[0],3072);
  274.       theRom=cartScratch;
  275.       break;
  276.     default:
  277.       break;
  278.     }
  279. }
  280.  
  281. /* Main hardware startup */
  282. void
  283. init_hardware (void)
  284. {
  285.   init_screen ();
  286.   init_riot ();
  287.   init_tia ();
  288.   init_raster ();
  289.   init_memory();
  290.   init_banking();
  291.   init_cpu (0xfffc);
  292. }
  293.  
  294. /* Do a raster change */
  295. inline void
  296. do_raster_change (int i, int type, int val, struct RasterChange *rc)
  297. {
  298.   if (beamadj == 0)
  299.     {
  300.       printf ("BEAMADJ == 0\n");
  301.  
  302.     }
  303.   rc->x = ebeamx + beamadj;
  304.   rc->type = type;
  305.   rc->val = val;
  306. }
  307.  
  308. /* Do a raster change on the unified list */
  309. /* type: type of change */
  310. /* val: value of change */
  311. inline void
  312. do_unified_change (int type, int val)
  313. {
  314.   if (unified_count < MAXLIST)
  315.     {
  316.       unified[unified_count].x = ebeamx + beamadj;
  317.       unified[unified_count].type = type;
  318.       unified[unified_count].val = val;
  319.       unified_count++;
  320.     }
  321. }
  322.  
  323. /* Do a player raster change */
  324. /* i: player to change. 0 or 1 */
  325. /* type: type of change */
  326. /* val: value of change */
  327. inline void
  328. do_plraster_change (int i, int type, int val)
  329. {
  330.   int plc = pl_change_count[i];
  331.   /*printf("Raster change i=%d, x=%d, type=%d, val=%d\n", i, x, type, val); */
  332.   if (plc < MAXLIST)
  333.     {
  334.       do_raster_change (i, type, val, &pl_change[i][plc]);
  335.       if (type == 1)
  336.     pl_change[i][plc].x -= 3;
  337.       pl_change_count[i]++;
  338.     }
  339. }
  340.  
  341. /* Do a playfield raster change */
  342. /* i: playfield to change. Depreciated, as 0 is now only one used */
  343. /* type: type of change */
  344. /* val: value of change */
  345. inline void
  346. do_pfraster_change (int i, int type, int val)
  347. {
  348.   int pfc = pf_change_count[i];
  349.   /*
  350.      if(ebeamy>=100) {
  351.      printf("Raster change i=%d, x=%d, type=%d, val=%d\n",
  352.      i, ebeamx+beamadj, type, val);
  353.      show();
  354.      }
  355.    */
  356.   if (pfc < MAXLIST)
  357.     {
  358.       do_raster_change (i, type, val, &pf_change[i][pfc]);
  359.       pf_change_count[i]++;
  360.     }
  361. }
  362.  
  363.  
  364. /* Use a unified change */
  365. /* rc: unified change structure to use */
  366. inline void
  367. use_unified_change (struct RasterChange *rc)
  368. {
  369.   switch (rc->type)
  370.     {
  371.     case 0:
  372.       /* P0MO colour */
  373.       colour_table[P0M0_COLOUR] = rc->val;
  374.       break;
  375.     case 1:
  376.       /* POM0 colour */
  377.       colour_table[P1M1_COLOUR] = rc->val;
  378.       break;
  379.     case 2:
  380.       /* PFBL colour */
  381.       colour_table[PFBL_COLOUR] = rc->val;
  382.       break;
  383.     case 3:
  384.       /* BK colour */
  385.       colour_table[BK_COLOUR] = rc->val;
  386.       break;
  387.     case 4:
  388.       /* Priority change Normal */
  389.       if(rc->val)
  390.     norm_val=1;
  391.       else
  392.     norm_val=0;
  393.       colour_lookup=colour_ptrs[norm_val][scores_val];
  394.       break;
  395.     case 5:
  396.       /* Priority change Scores */
  397.       if(rc->val)
  398.     {
  399.       if(rc->x < 80)
  400.         scores_val=1;
  401.       else
  402.         scores_val=2;
  403.     }
  404.       else
  405.     scores_val=0;
  406.       colour_lookup=colour_ptrs[norm_val][scores_val];
  407.       break;
  408.     }
  409. }
  410.  
  411. /* Use a playfield change */
  412. /* pl: playfield to change */
  413. /* rc: change to make */
  414. inline void
  415. use_pfraster_change (struct PlayField *pl, struct RasterChange *rc)
  416. {
  417.   switch (rc->type)
  418.     {
  419.     case 0:
  420.       /* PF0 */
  421.       pl->pf0 = rc->val;
  422.       break;
  423.     case 1:
  424.       /* PF1 */
  425.       pl->pf1 = rc->val;
  426.       break;
  427.     case 2:
  428.       /* PF2 */
  429.       pl->pf2 = rc->val;
  430.       break;
  431.     case 3:
  432.       /* Reflection */
  433.       pl->ref = rc->val;
  434.       break;
  435.     }
  436. }
  437.  
  438. /* Use a player change */
  439. /* pl: player to change */
  440. /* rc: change to make */
  441. inline void
  442. use_plraster_change (struct Player *pl, struct RasterChange *rc)
  443. {
  444.   switch (rc->type)
  445.     {
  446.     case 0:
  447.       /* GRP */
  448.       pl->grp = rc->val;
  449.       break;
  450.       /* Vertical delay */
  451.     case 1:
  452.       pl->vdel = pl->grp;
  453.       break;
  454.     }
  455. }
  456.  
  457.  
  458. int
  459. do_paddle (int padnum)
  460. {
  461.   int res = 0x80;
  462.   int x;
  463.   if ((tiaWrite[VBLANK] & 0x80) == 0)
  464.     {
  465.       x = 320 - mouse_position ();
  466.       x = x * 45;
  467.       x += paddle[padnum].val;
  468.       if (x > clk)
  469.     res = 0x00;
  470.     }
  471.   return res;
  472. }
  473.  
  474. /* Calculate the keypad rows */
  475. /* i.e. when reading from INPTx we don't know the row */
  476. BYTE
  477. do_keypad (int pad, int col)
  478. {
  479.   BYTE res= 0x80;
  480.  
  481.   /* Bottom row */
  482.   if(pad==0) {
  483.   if( (riotWrite[SWCHA] & 0x80) && keypad[pad][col]==3)
  484.     res=0x00;
  485.   /* Third row */
  486.   if( (riotWrite[SWCHA] & 0x40) && keypad[pad][col]==2)
  487.     res=0x00;
  488.   if( (riotWrite[SWCHA] & 0x20) && keypad[pad][col]==1)
  489.     res=0x00;
  490.   if( (riotWrite[SWCHA] & 0x10) && keypad[pad][col]==0)
  491.     res=0x00;
  492.   }
  493.   else {
  494.   /* Bottom row */
  495.   if( (riotWrite[SWCHA] & 0x80) && keypad[pad][col]==3)
  496.     res=0x00;
  497.   /* Third row */
  498.   if( (riotWrite[SWCHA] & 0x40) && keypad[pad][col]==2)
  499.     res=0x00;
  500.   if( (riotWrite[SWCHA] & 0x20) && keypad[pad][col]==1)
  501.     res=0x00;
  502.   if( (riotWrite[SWCHA] & 0x10) && keypad[pad][col]==0)
  503.     res=0x00;
  504.   }
  505.   return res;
  506. }
  507.  
  508.  
  509. /*
  510.    Called when the timer is set .
  511.    Note that res is the bit shift, not absolute value.
  512.    Assumes that any timer interval set will last longer than the instruction
  513.    setting it.
  514.  */
  515. /* res: timer interval resolution as a bit shift value */
  516. /* count: the number of intervals to set */
  517. /* clkadj: the number of CPU cycles into the current instruction  */
  518. void
  519. set_timer (int res, int count, int clkadj)
  520. {
  521.   timer_count = count << res;
  522.   timer_clks = (int) clk + clkadj;
  523.   timer_res = res;
  524. }
  525.  
  526. /* New timer code, now only called on a read of INTIM */
  527. /* clkadj: the number of CPU cycles into the current instruction  */
  528. /* returns: the current timer value */
  529. BYTE
  530. do_timer (int clkadj)
  531. {
  532.   BYTE result;
  533.   int delta;
  534.   int value;
  535.  
  536.   delta = (int) clk - timer_clks;
  537.   value = delta >> timer_res;
  538.   if (delta <= timer_count)
  539.     {                /* Timer is still going down in res intervals */
  540.       result = value;
  541.     }
  542.   else
  543.     {
  544.       if (value == 0)
  545.     /* Timer is in holding period */
  546.     result = 0;
  547.       else
  548.     {
  549.       /* Timer is descending from 0xff in clock intervals */
  550.       set_timer (0, 0xff, clkadj);
  551.       result = 0;
  552.     }
  553.     }
  554.  
  555.   /*  printf("Timer result=%d\n", result); */
  556.   return result;
  557. }
  558.  
  559. /* Do the screen related part of a write to VBLANK */
  560. /* b: the byte written */
  561. void
  562. do_vblank (BYTE b)
  563. {
  564.   if (b & 0x02)
  565.     {
  566.       /* Start vertical blank */
  567.       vbeam_state = VBLANKSTATE;
  568.       /* Also means we can update screen */
  569.       sound_update ();
  570.       tv_event ();
  571.       tv_display ();
  572.       /* Only wait if we're on a faster display */
  573.     }
  574.   else
  575.     {
  576.       /* End vblank, and start first hsync drawing */
  577.       int i;
  578.  
  579.       vbeam_state = DRAWSTATE;
  580.       hbeam_state = HSYNCSTATE;
  581.       /* Set up the screen */
  582.       for (i = 0; i < unified_count; i++)
  583.     use_unified_change (&unified[i]);
  584.       /* Hope for a WSYNC, but just in case */
  585.       ebeamx = -tv_hsync;
  586.       ebeamy = 0;
  587.     }
  588. }
  589.  
  590.  
  591. /* do a horizontal sync */
  592. void
  593. do_hsync (void)
  594. {
  595.   /* Only perform heavy stuff if electron beam is in correct position */
  596.   if (vbeam_state == DRAWSTATE && (ebeamx > -tv_hsync))
  597.     {
  598.       tv_raster (ebeamy);
  599.       /* Fix the clock value */
  600.       clk += (long)((ebeamx - tv_width) / 3);
  601.       ebeamy++;
  602.     }
  603.   hbeam_state = HSYNCSTATE;
  604.   ebeamx = -tv_hsync;
  605.   sbeamx = 0;
  606. }
  607.  
  608. /* Main screen logic */
  609. /* clks: CPU clock length of last instruction */
  610. void
  611. do_screen (int clks)
  612. {
  613.   switch (vbeam_state)
  614.     {
  615.     case VSYNCSTATE:
  616.     case VBLANKSTATE:
  617.       switch (hbeam_state)
  618.     {
  619.     case HSYNCSTATE:
  620.       ebeamx += clks * 3;
  621.       if (ebeamx >= 0)
  622.         {
  623.           hbeam_state = DRAWSTATE;
  624.         }
  625.       break;
  626.     case DRAWSTATE:
  627.       ebeamx += clks * 3;
  628.       if (ebeamx >= tv_width)
  629.         {
  630.           ebeamx -= (tv_hsync + tv_width);
  631.           /* Insert hsync stuff here */
  632.           sbeamx = ebeamx;
  633.           hbeam_state = HSYNCSTATE;
  634.         }
  635.       break;
  636.     case OVERSTATE:
  637.       break;
  638.     }
  639.       break;
  640.     case DRAWSTATE:
  641.       switch (hbeam_state)
  642.     {
  643.     case HSYNCSTATE:
  644.       ebeamx += clks * 3;
  645.       if (ebeamx >= 0)
  646.         {
  647.           hbeam_state = DRAWSTATE;
  648.         }
  649.       break;
  650.     case DRAWSTATE:
  651.       ebeamx += clks * 3;
  652.       if (ebeamx >= tv_width)
  653.         {
  654.           /* Insert hsync stuff here */
  655.           sbeamx = ebeamx;
  656.           ebeamx -= (tv_hsync + tv_width);
  657.           tv_raster (ebeamy);
  658.           ebeamy++;
  659.           hbeam_state = HSYNCSTATE;
  660.         }
  661.       if (ebeamy >= tv_height + tv_overscan)
  662.         {
  663.           vbeam_state = OVERSTATE;
  664.           ebeamy = 0;
  665.         }
  666.       break;
  667.     case OVERSTATE:
  668.       break;
  669.     }
  670.       break;
  671.     case OVERSTATE:
  672.       break;
  673.     }
  674. }
  675.