Subversion Repositories pentevo

Rev

Rev 716 | Blame | Last modification | View Log | Download | RSS feed

  1. #include "std.h"
  2.  
  3. #include "emul.h"
  4. #include "vars.h"
  5. #include "memory.h"
  6. #include "draw.h"
  7.  
  8. void atm_memswap()
  9. {
  10.    if (!conf.atm.mem_swap) return;
  11.    // swap memory address bits A5-A7 and A8-A10
  12.    for (unsigned start_page = 0; start_page < conf.ramsize*1024; start_page += 2048) {
  13.       unsigned char buffer[2048], *bank = memory + start_page;
  14.       for (unsigned addr = 0; addr < 2048; addr++)
  15.          buffer[addr] = bank[(addr & 0x1F) + ((addr >> 3) & 0xE0) + ((addr << 3) & 0x700)];
  16.       memcpy(bank, buffer, 2048);
  17.    }
  18. }
  19.  
  20. void AtmApplySideEffectsWhenChangeVideomode(unsigned char val)
  21. {
  22.     int NewVideoMode = (val & 7);
  23.     int OldVideoMode = (comp.pFF77 & 7);
  24.  
  25.     // ╩юэёЄрэЄ√ ьюцэю чрфрЄ№ ц╕ёЄъю, яюЄюьє ўЄю ьхцфє ьюфхы ьш └╥╠2 юэш эх ьхэ ■Єё .
  26.     const int tScanlineWidth = 224;
  27.     const int tScreenWidth = 320/2;
  28.     const int tEachBorderWidth = (tScanlineWidth - tScreenWidth)/2;
  29.     const int iLinesAboveBorder = 56;
  30.  
  31.     int iRayLine = cpu.t / tScanlineWidth;
  32.     int iRayOffset = cpu.t % tScanlineWidth;
  33. /*    
  34.     static int iLastLine = 0;
  35.     if ( iLastLine > iRayLine )
  36.     {
  37.         printf("\nNew Frame Begin\n");
  38.         __debugbreak();
  39.     }
  40.     iLastLine = iRayLine;
  41.     printf("%d->%d %d %d\n", OldVideoMode, NewVideoMode, iRayLine, iRayOffset);
  42. */
  43.  
  44.     if (OldVideoMode == 3 || NewVideoMode == 3)
  45.     {
  46.         // ╧хЁхъы■ўхэшх шч/т sinclair Ёхцшь эх шьххЄ яюыхчэ√ї яюсюўэ√ї ¤ЇЇхъЄют
  47.         // (яю ёыютрь AlCo фрцх ёшэїЁр ёсштрхЄё )
  48.         for(unsigned y = 0; y < 200; y++)
  49.         {
  50.             AtmVideoCtrl.Scanlines[y+56].VideoMode = NewVideoMode;
  51.             AtmVideoCtrl.Scanlines[y+56].Offset = ((y & ~7) << 3) + 0x01C0;
  52.         }
  53.         return;
  54.     }
  55.  
  56.     if (OldVideoMode != 6 && NewVideoMode != 6)
  57.     {
  58.         // ═рё шэЄхЁхёє■Є Єюы№ъю яхЁхъы■ўхэш  ьхцфє ЄхъёЄют√ь Ёхцшьюь ш Ёрё°шЁхээ√ьш уЁрЇшўхёъшьш.
  59.         // ╥хъёЄютюую Ёхцшьр эхЄ эш фю, эш яюёых яхЁхъы■ўхэш .
  60.         // ╤ыхфютрЄхы№эю, эхЄ ш яюсюўэ√ї ¤ЇЇхъЄют.
  61.        
  62.         // ╨рёяЁюёЄЁрэ хь эют√щ тшфхюЁхцшь эр эхюЄЁшёютрээ√х ёърэышэшш
  63.         if (iRayOffset >= tEachBorderWidth)
  64.             ++iRayLine;
  65.  
  66.         while (iRayLine < 256)
  67.         {
  68.             AtmVideoCtrl.Scanlines[iRayLine++].VideoMode = NewVideoMode;
  69.         }
  70. //        printf("%d->%d SKIPPED!\n",  OldVideoMode, NewVideoMode);
  71.         return;
  72.     }
  73.  
  74.     //
  75.     // ╥хЁьшэюыюуш  ш ъюэёЄрэЄ√:
  76.     // ▌ъЁрэ ёюфхЁцшЄ 312 ёърэышэшщ, яю 224ЄръЄр (noturbo) т ърцфющ.
  77.     //
  78.     //  "ёЄЁюър" - ьырф°шх 3 сшЄр эюьхЁр юЄЁшёют√трхьющ тшфхюъюэЄЁюыыхЁюь (ыєўюь) ёърэышэшш
  79.     //  "рфЁхё"  - Єхъє∙шщ рфЁхё т тшфхюярь Єш, ё ъюЄюЁюую т√сшЁрхЄ срщЄ√ тшфхюъюэЄЁюыыхЁ
  80.     //             рфЁхё ьхэ хЄё  ё уЁрэєы ЁэюёЄ№■ +8 шыш +64
  81.     //  "¤ъЁрэ"  - ЁрёЄЁютр  ърЁЄшэър. ╤ю тёхї ёЄюЁюэ юъЁєцхэр "сюЁф■Ёюь".
  82.     //             ╨рчьхЁ√ сюЁф■Ёр:
  83.     //          ётхЁїє ш ёэшчє юЄ ЁрёЄЁр: 56 ёърэышэшщ
  84.     //              ёыхтр ш ёяЁртр юЄ ЁрёЄЁр: 32 ЄръЄр (64яшъёхы ).
  85.     //
  86.     // +64 яЁюшёїюфшЄ, ъюуфр CROW 1->0, Єю хёЄ№:
  87.     //  ышсю т ЄхъёЄьюфх яЁш яхЁхїюфх ёю ёЄЁюъш 7 эр ёЄЁюъє 0,
  88.     //  ышсю яЁш яхЁхъы■ўхэшш ЄхъёЄьюф->уЁрЇшър яЁш рфЁхёх A5=0,
  89.     //  ышсю яЁш яхЁхъы■ўхэшш уЁрЇшър->ЄхъёЄьюф яЁш рфЁхёх A5=1 ш ёЄЁюъх 0..3
  90.     //
  91.     // +8 яЁюшёїюфшЄ эр ЁрёЄЁх т ъюэЎх 64-сыюър яшъёхыхщ (ърцф√х 32ЄръЄр) эхчртшёшью юЄ Ёхцшьр
  92.     // (┬└╞═╬: +8 эх чртЁряыхэ√ тэєЄЁш A3..A5 р яЁюшчтюф Є ўхёЄэюх ёыюцхэшх ё рфЁхёюь.)
  93.     //
  94.     // ёсЁюё A3..A5 (эръюяыхээ√ї +8) яЁюшёїюфшЄ, ъюуфр RCOL 1->0, Єю хёЄ№:
  95.     //  ышсю т ЄхъёЄьюфх яЁш яхЁхїюфх ё ЁрёЄЁр эр сюЁф■Ё,
  96.     //  ышсю эр сюЁф■Ёх яЁш яхЁхъы■ўхэшш уЁрЇшър->ЄхъёЄьюф
  97.     //
  98.  
  99.  
  100.     if (iRayLine >= 256)
  101.     {
  102.         return;
  103.     }
  104.  
  105.     // ╧юыєўшь юЇЇёхЄ Єхъє∙хщ ёърэышэшш (ЇръЄшўхёъш тшфхюрфЁхё х╕ эрўрыр)
  106.     int Offset = AtmVideoCtrl.Scanlines[iRayLine].Offset;
  107.  
  108.     // ┬√ўшёышь Ёхры№э√щ тшфхюрфЁхё, ё єў╕Єюь шэъЁхьхэЄют яЁш юЄЁшёютъх ЁрёЄЁр.
  109.     // ╥ръцх юяЁхфхышь, ъєфр яЁшьхэ хь +64 шэъЁхьхэЄ√ яЁш яхЁхъы■ўхэшш тшфхюЁхцшьр:
  110.     //  - ┼ёыш ыєў эр сюЁф■Ёх ётхЁїє юЄ ЁрёЄЁр шыш эр сюЁф■Ёх ёыхтр юЄ ЁрёЄЁр - шчьхэ хь юЇЇёхЄ фы  Єхъє∙хщ ёърэышэшш
  111.     //  - ┼ёыш ыєў эр ЁрёЄЁх шыш эр сюЁф■Ёх ёяЁртр юЄ ЁрёЄЁр - шчьхэ хь юЇЇёхЄ фы  ёыхфє■∙хщ ёърэышэшш
  112.     bool bRayOnBorder = true;
  113.     if ( iRayLine < iLinesAboveBorder || iRayOffset < tEachBorderWidth )
  114.     {
  115.         // ╦єў эр сюЁф■Ёх. ╦шсю ётхЁїє юЄ ЁрёЄЁр, ышсю ёыхтр юЄ ЁрёЄЁр.
  116.         // ┬ёх шчьхэхэш  яЁшьхэ хь ъ Єхъє∙хщ ёърэышэшш.
  117.  
  118.         // ╬сЁрсюЄрхь яхЁхъы■ўхэшх тшфхюЁхцшьр.
  119.         if ( NewVideoMode == 6 )
  120.         {
  121.             // ╧хЁхъы■ўхэшх ┬ ЄхъёЄют√щ Ёхцшь.
  122.             if ( (Offset & 32) //< яЁютхЁър єёыютш  "яЁш рфЁхёх A5=1"
  123.                  && (iRayLine & 7) < 4 //< яЁютхЁър єёыютш  "т ёЄЁюъх 0..3"
  124.                )
  125.             {
  126. //                printf("CASE-1: 0x%.4x Incremented (+64) on line %d\n", Offset, iRayLine);
  127.                 Offset += 64;
  128.                 AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
  129.             }
  130.  
  131.             AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
  132.  
  133.             // ╧юёых яЁюїюфр тёхї Єюўхъ ЁрёЄЁр Єхъє∙хщ ёърэышэшш т ЄхъёЄютюь Ёхцшьх сєфєЄ ёсЁю°хэ√ A3..A5
  134.             Offset &= (~0x38); // ╤сЁюё A3..A5
  135. //            printf("CASE-1a, reset A3..A5: 0x%.4x\n", Offset);
  136.            
  137.             // ╨рёёў╕Є тшфхюрфЁхёют фы  эшцыхцр∙шї ёърэышэшщ
  138.             while (++iRayLine < 256)
  139.             {
  140.                 if ( 0 == (iRayLine & 7))
  141.                 {
  142.                     Offset += 64;
  143.                 }
  144.                 AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
  145.                 AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
  146.             }
  147.         } else {
  148.             // ╧хЁхъы■ўхэшх ╚╟ ЄхъёЄютюую Ёхцшьр.
  149.             if ( 0 == (Offset & 32) ) //< яЁютхЁър єёыютш  "яЁш рфЁхёх A5=0"
  150.             {
  151. //                printf("CASE-2: 0x%.4x Incremented (+64) on line %d\n", Offset, iRayLine);
  152.                 Offset += 64;
  153.                 AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
  154.             }
  155.             AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
  156.  
  157.             // ╨рёёў╕Є тшфхюрфЁхёют фы  эшцыхцр∙шї ёърэышэшщ
  158.             while (++iRayLine < 256)
  159.             {
  160.                 AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
  161.                 AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
  162.             }
  163.         }
  164.     } else {
  165.         // ╦єў ЁшёєхЄ ЁрёЄЁ, ышсю сюЁф■Ё ёяЁртр юЄ ЁрёЄЁр.
  166.  
  167.         // ┬√ўшёы хь Єхъє∙хх чэрўхэшх тшфхюрфЁхёр
  168.  
  169.         // ╧Ёшсрты хь ъ тшфхюрфЁхёє тёх +64 шэъЁхьхэЄ√,
  170.         // ёфхырээ√х т їюфх юЄЁшёютъш ЁрёЄЁр фрээющ ёърэышэшш
  171.         if (iRayLine == AtmVideoCtrl.CurrentRayLine)
  172.         {
  173.             Offset += AtmVideoCtrl.IncCounter_InRaster;
  174.         } else {
  175.             // ╤ў╕Єўшъ шэъЁхьхэЄют єёЄрЁхы (Є.ъ. эръЁєўхэ эр ёърэышэш■ юЄышўэє■ юЄ Єхъє∙хщ)
  176.             // ╚эшЎшрышчшЁєхь хую фы  Єхъє∙хщ ёърэышэшш.
  177.             AtmVideoCtrl.CurrentRayLine = iRayLine;
  178.             AtmVideoCtrl.IncCounter_InRaster = 0;
  179.             AtmVideoCtrl.IncCounter_InBorder = 0;
  180.         }
  181.        
  182.         // ╧Ёшсрты хь ъ тшфхюрфЁхёє тёх +8 шэъЁхьхэЄ√, яЁюшчю°хф°шх яЁш юЄЁшёютъх ЁрёЄЁр
  183.         bool bRayInRaster = iRayOffset < (tScreenWidth + tEachBorderWidth);
  184.        
  185.         int iScanlineRemainder = 0; //< ╤ъюы№ъю +8 шэъЁхьхэЄют х∙╕ сєфхЄ ёфхырэю фю ъюэЎр ёърэышэшш
  186.                                     //  (Є.х. єцх яюёых яхЁхъы■ўхэш  тшфхюЁхцшьр)
  187.         if ( bRayInRaster )
  188.         {
  189.             // ╦єў ЁшёєхЄ ЁрёЄЁ.
  190.             // ╧Ёшсрты хь ъ Єхъє∙хьє тшфхюрфЁхёє ёЄюы№ъю +8,
  191.             // ёъюы№ъю с√ыю яюыэюёЄ№■ юЄЁшёютрээ√ї 64яшъёхы№э√ї сыюър.
  192.             int iIncValue = 8 * ((iRayOffset-tEachBorderWidth)/32);
  193.             iScanlineRemainder = 40 - iIncValue;
  194. //            printf("CASE-4: 0x%.4x Incremented (+%d) on line %d\n", Offset, iIncValue, iRayLine);
  195.             Offset += iIncValue;
  196.         } else {
  197.             // ╬ЄЁшёютър ЁрёЄЁр ыєўюь чртхЁ°хэр.
  198.             // ╥.х. тёх 5- Є№ 64-яшъёхы№э√ї сыюър с√ыш яЁющфхэ√. ╧Ёшсрты хь ъ рфЁхёє +40.
  199. //            printf("CASE-5: 0x%.4x Incremented (+40) on line %d\n", Offset, iRayLine);
  200.             Offset += 40;
  201.  
  202.             // ┼ёыш яЁхф√фє∙шь Ёхцшьюь с√ы ЄхъёЄют√щ Ёхцшь,
  203.             // ╥ю яЁш яхЁхїюфх ё ЁрёЄЁр эр сюЁф■Ё фюыцэ√ с√Є№ ёсЁю°хэ√ A3..A5
  204.             if (OldVideoMode == 6)
  205.             {
  206.                 Offset &= (~0x38); // ╤сЁюё A3..A5
  207. //                printf("CASE-5a, reset A3..A5: 0x%.4x\n", Offset);
  208.             }
  209.         }
  210.  
  211.         // ╧Ёшсрты хь ъ тшфхюрфЁхёє тёх +64 шэъЁхьхэЄ√,
  212.         // ёфхырээ√х т їюфх юЄЁшёютъш сюЁф■Ёр чр ЁрёЄЁюь фрээющ ёърэышэшш
  213.         Offset += AtmVideoCtrl.IncCounter_InBorder;
  214.  
  215.         // ╥хъє∙хх чэрўхэшх тшфхюрфЁхёр т√ўшёыхэю.
  216.         // ╬сЁрсрЄ√трхь яхЁхъы■ўхэшх тшфхюЁхцшьр.
  217.         int OffsetInc = 0;
  218.         if ( NewVideoMode == 6 )
  219.         {
  220.             // ╧хЁхъы■ўхэшх ┬ ЄхъёЄют√щ Ёхцшь.
  221.             if ( (Offset & 32) //< яЁютхЁър єёыютш  "яЁш рфЁхёх A5=1"
  222.                 && (iRayLine & 7) < 4 //< яЁютхЁър єёыютш  "т ёЄЁюъх 0..3"
  223.                 )
  224.             {
  225.                 OffsetInc = 64;
  226. //                printf("CASE-6: 0x%.4x Incremented (+64) on line %d\n", Offset, iRayLine);
  227.                 Offset += OffsetInc;
  228.             }
  229.             // ╨рёёў╕Є тшфхюрфЁхёют фы  эшцыхцр∙шї ёърэышэшщ
  230.             Offset += iScanlineRemainder;
  231.             while (++iRayLine < 256)
  232.             {
  233.                 if ( 0 == (iRayLine & 7))
  234.                     Offset += 64;
  235.                 AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
  236.                 AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
  237.             }
  238.         } else {
  239.             // ╧хЁхъы■ўхэшх ╚╟ ЄхъёЄютюую Ёхцшьр.
  240.             if ( 0 == (Offset & 32) ) //< яЁютхЁър єёыютш  "яЁш рфЁхёх A5=0"
  241.             {
  242.                 OffsetInc = 64;
  243. //                printf("CASE-7: 0x%.4x Incremented (+64) on line %d\n", Offset, iRayLine);
  244.                 Offset += OffsetInc;
  245.             }
  246.  
  247.             // ╨рёёў╕Є тшфхюрфЁхёют фы  эшцыхцр∙шї ёърэышэшщ
  248.             Offset += iScanlineRemainder;
  249.             while (++iRayLine < 256)
  250.             {
  251.                 AtmVideoCtrl.Scanlines[iRayLine].Offset = Offset;
  252.                 AtmVideoCtrl.Scanlines[iRayLine].VideoMode = NewVideoMode;
  253.                 Offset += 40;
  254.             }
  255.         }
  256.  
  257.         // чряюьшэрхь ёфхырээ√щ шэъЁхьхэЄ эр ёыєўрщ,
  258.         // хёыш шї сєфхЄ эхёъюы№ъю т їюфх юЄЁшёютъш Єхъє∙хщ ёърэышэшш.
  259.         if ( bRayInRaster )
  260.         {
  261.             AtmVideoCtrl.IncCounter_InRaster += OffsetInc;
  262.         } else {
  263.             AtmVideoCtrl.IncCounter_InBorder += OffsetInc;
  264.         }
  265.     }
  266. }
  267.  
  268. void set_atm_FF77(unsigned port, unsigned char val)
  269. {
  270.    if ((comp.pFF77 ^ val) & 1)
  271.        atm_memswap();
  272.    
  273.  
  274.    if ((comp.pFF77 & 7) ^ (val & 7))
  275.    {
  276.         // ╧ЁюшёїюфшЄ яхЁхъы■ўхэшх тшфхюЁхцшьр
  277.         AtmApplySideEffectsWhenChangeVideomode(val);
  278.    }
  279.  
  280.    comp.pFF77 = val;
  281.    comp.aFF77 = port;
  282.    cpu.int_gate = (comp.pFF77 & 0x20) != false;
  283.    set_banks();
  284. }
  285.  
  286. void set_atm_aFE(unsigned char addr)
  287. {
  288.    unsigned char old_aFE = comp.aFE;
  289.    comp.aFE = addr;
  290.    if ((addr ^ old_aFE) & 0x40) atm_memswap();
  291.    if ((addr ^ old_aFE) & 0x80) set_banks();
  292. }
  293.  
  294. static u8 atm_pal[0x10] = { 0 };
  295.  
  296. void atm_writepal(unsigned char val)
  297. {
  298.    assert(comp.border_attr < 0x10);
  299.    atm_pal[comp.border_attr] = val;
  300.    comp.comp_pal[comp.border_attr] = t.atm_pal_map[val];
  301.    temp.comp_pal_changed = 1;
  302. }
  303.  
  304. u8 atm_readpal()
  305. {
  306.    return atm_pal[comp.border_attr];
  307. }
  308.  
  309. unsigned char atm450_z(unsigned t)
  310. {
  311.    // PAL hardware gives 3 zeros in secret short time intervals
  312.    if (conf.frame < 80000) { // NORMAL SPEED mode
  313.       if ((unsigned)(t-7200) < 40 || (unsigned)(t-7284) < 40 || (unsigned)(t-7326) < 40) return 0;
  314.    } else { // TURBO mode
  315.       if ((unsigned)(t-21514) < 40 || (unsigned)(t-21703) < 80 || (unsigned)(t-21808) < 40) return 0;
  316.    }
  317.    return 0x80;
  318. }
  319.