home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / GAMES / infocom_src.lha / page.c < prev    next >
Text File  |  1993-03-03  |  5KB  |  228 lines

  1. /*
  2. **    File:    page.c
  3. **
  4. **    (C)opyright 1987-1992 InfoTaskforce.
  5. */
  6.  
  7. #include    "infocom.h"
  8.  
  9. /*
  10. **    Page Table Structure Definition ( see "infocom.h" ).
  11. **
  12. **
  13. **        typedef struct
  14. **        {
  15. **            word        page ;
  16. **            long_word    count ;
  17. **            word        padding ;
  18. **        } page_table_t ;
  19. **
  20. **        typedef        page_table_t            *page_table_ptr ;
  21. **
  22. **
  23. **    Field Usage:
  24. **
  25. **        page    : Number of the page occupying this page table block.
  26. **        count    : Time stamp - used by the LRU algorithm.
  27. **        padding    : This field was inserted to make the size of the
  28. **                  page_table_t structure a power of 2 - thus easier
  29. **                  for the compiler to optimise.
  30. */
  31.  
  32. /*
  33. **    Page Table Global Variables.
  34. **
  35. **    Many of these variables must retain their values
  36. **    between invocations of the paging functions.
  37. **
  38. **    These are:
  39. **
  40. **        tick            : Current Tick Count - used to timestamp new table
  41. **                          entries.
  42. **        prog_page        : Number of the page containing the currently
  43. **                          executing opcode.
  44. **        MRU_page        : Number of the "Most Recently Used" page.
  45. **        MRU_block_ptr    : Pointer to the page table block containing the
  46. **                          "Most Recently Used" page.
  47. **        page_strt        : Pointer to the first page table block.
  48. **        MRU                : Pointer to the page table entry of the
  49. **                          "Most Recently Used" page.
  50. **        page_entry        : Pointer to the page table entry of the page
  51. **                          containing the currently executing opcode. This
  52. **                          is a NULL pointer if the current opcode came
  53. **                          from a resident block.
  54. **        strt_page_table    : The Page Table Entry Array.
  55. **
  56. */
  57.  
  58. long_word        tick            = 0 ;
  59. word            prog_page        = EMPTY_PAGE ;
  60. word            MRU_page        = EMPTY_PAGE ;
  61. byte_ptr        MRU_block_ptr    = (byte_ptr)0 ;
  62. byte_ptr        page_strt        = (byte_ptr)0 ;
  63. page_table_ptr    MRU                = (page_table_ptr)0 ;
  64. page_table_ptr    page_entry        = (page_table_ptr)0 ;
  65. page_table_ptr    strt_page_table    = (page_table_ptr)0 ;
  66.  
  67. Void
  68. init_page ( ptr,num_pages )
  69. byte_ptr    ptr ;
  70. word        num_pages ;
  71. {
  72.     extern byte_ptr        base_ptr ;
  73.  
  74.     page_table_ptr        page_ptr ;
  75.     
  76.     page_strt = ptr ;
  77.     page_ptr = strt_page_table ;
  78.     while ( num_pages-- )
  79.     {
  80.         page_ptr -> page = EMPTY_PAGE ;
  81.         page_ptr -> count = 0 ;
  82.         ++page_ptr ;
  83.     }
  84.  
  85.     /*
  86.     **    Mark end of Page Table
  87.     */
  88.  
  89.     page_ptr -> page = END_OF_TABLE ;
  90.     page_ptr -> count = 0 ;
  91. }
  92.  
  93. byte_ptr
  94. fetch_page ( new_page )
  95. word    new_page ;
  96. {
  97.     page_table_ptr    ptr ;
  98.     boolean            found ;
  99.  
  100.     if ( MRU_page != new_page )
  101.     {
  102.         found = FALSE ;
  103.         MRU_page = new_page ;
  104.         ++tick ;
  105.         ptr = strt_page_table ;
  106.  
  107.         while (( ptr -> page != END_OF_TABLE ) && ( found == FALSE ))
  108.         {
  109.             if ( ptr -> page == new_page )
  110.             {
  111.                 if ( prog_page != new_page )
  112.                     ptr -> count = tick ;
  113.                 MRU = ptr ;
  114.                 MRU_block_ptr = page_strt +
  115.                         ((signed_long)(MRU - strt_page_table) * BLOCK_SIZE) ;
  116.                 found = TRUE ;
  117.             }
  118.             else
  119.                 ++ptr ;
  120.         }
  121.         if ( found == FALSE )
  122.         {
  123.             MRU = get_LRU_page () ;
  124.             MRU -> page = MRU_page ;
  125.             MRU -> count = tick ;
  126.             MRU_block_ptr = page_strt +
  127.                         ((signed_long)(MRU - strt_page_table) * BLOCK_SIZE) ;
  128.             load_page ( MRU_page,1,MRU_block_ptr ) ;
  129.         }
  130.     }
  131.     return ( MRU_block_ptr ) ;
  132. }
  133.  
  134. page_table_ptr
  135. get_LRU_page ()
  136. {
  137.     long_word        test ;
  138.     page_table_ptr    LRU ;
  139.     page_table_ptr    ptr ;
  140.  
  141.     ptr = strt_page_table ;
  142.     test = MAX_COUNT ;
  143.     while ( ptr -> page != END_OF_TABLE )
  144.     {
  145.         if ( test >= ptr -> count )
  146.         {
  147.             test = ptr -> count ;
  148.             LRU = ptr ;
  149.         }
  150.         ++ptr ;
  151.     }
  152.     return ( LRU ) ;
  153. }
  154.  
  155. Void
  156. fix_pc ()
  157. {
  158.     extern word            pc_page ;
  159.     extern word            pc_offset ;
  160.     extern word            resident_blocks ;
  161.     extern byte_ptr        prog_block_ptr ;
  162.     extern byte_ptr        pc ;
  163.     extern byte_ptr        base_ptr ;
  164.  
  165.     /*
  166.     **    Note:
  167.     **        'pc_page' is unsigned and can have any value from $0000 to $FFFF.
  168.     **        The high bit of 'pc_offset' is actually a sign bit.
  169.     */
  170.  
  171.     /*
  172.     **    The old way of generating pc_page and pc_offset (VERSIONS 1, 2 & 3):
  173.     **
  174.     **        signed_long        ipc ;
  175.     **
  176.     **        ipc = ((signed_long)pc_page * BLOCK_SIZE) + (signed_word)pc_offset ;
  177.     **        pc_page = ipc / BLOCK_SIZE ;
  178.     **        pc_offset = ipc % BLOCK_SIZE ;
  179.     **
  180.     **    The new way of generating pc_page and pc_offset (VERSIONS 4 & 5):
  181.     **
  182.     **        signed_word        offset ;
  183.     **
  184.     **        offset = (signed_word)pc_offset / (int)BLOCK_SIZE ;
  185.     **        if ((signed_word)pc_offset < 0 )
  186.     **            --offset ;
  187.     **        if ( offset )
  188.     **            pc_page += offset ;
  189.     **        pc_offset %= BLOCK_SIZE ;
  190.     **
  191.     **    This is a bit messy. The old way is still being used because some
  192.     **    compiler libraries do not correctly handle the modulo operation (%)
  193.     **    if the arguments are negative.
  194.     **
  195.     **    Note: In the line:
  196.     **        offset = (signed_word)pc_offset / (int)BLOCK_SIZE ;
  197.     **                                            ^
  198.     **                                            |
  199.     **    the above casting is required by the LSC Compiler in order for
  200.     **    signed division to occur.
  201.     */
  202.     
  203.     signed_long        ipc ;
  204.  
  205.     ipc = ( (signed_long)pc_page * BLOCK_SIZE ) + (signed_word)pc_offset ;
  206.     pc_page = ipc / (int)BLOCK_SIZE ;
  207.     pc_offset = ipc % (int)BLOCK_SIZE ;
  208.  
  209.     if ( prog_page != pc_page )
  210.     {
  211.         prog_page = pc_page ;
  212.         if ( page_entry != (page_table_ptr)0 )
  213.             page_entry -> count = tick ;
  214.         if ( pc_page < resident_blocks )
  215.         {
  216.             prog_block_ptr = base_ptr + ((signed_long)pc_page * BLOCK_SIZE) ;
  217.             page_entry = (page_table_ptr)0 ;
  218.         }
  219.         else
  220.         {
  221.             prog_block_ptr = fetch_page ( pc_page ) ;
  222.             page_entry = MRU ;
  223.             page_entry -> count = MAX_COUNT ;
  224.         }
  225.     }
  226.     pc = prog_block_ptr + (signed_word)pc_offset ;
  227. }
  228.