Subversion Repositories pentevo

Rev

Rev 796 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. #include "std.h"
  2.  
  3. #include "emul.h"
  4. #include "vars.h"
  5. #include "memory.h"
  6. #include "draw.h"
  7. #include "atm.h"
  8.  
  9. static void atm_memswap()
  10. {
  11.    if (!conf.atm.mem_swap) return;
  12.    // swap memory address bits A5-A7 and A8-A10
  13.    for (unsigned start_page = 0; start_page < conf.ramsize*1024; start_page += 2048) {
  14.       unsigned char buffer[2048], *bank = memory + start_page;
  15.       for (unsigned addr = 0; addr < 2048; addr++)
  16.          buffer[addr] = bank[(addr & 0x1F) + ((addr >> 3) & 0xE0) + ((addr << 3) & 0x700)];
  17.       memcpy(bank, buffer, 2048);
  18.    }
  19. }
  20.  
  21. static void AtmApplySideEffectsWhenChangeVideomode(unsigned char val)
  22. {
  23.     int NewVideoMode = (val & 7);
  24.     int OldVideoMode = (comp.pFF77 & 7);
  25.  
  26.     // ╩юэёЄрэЄ√ ьюцэю чрфрЄ№ ц╕ёЄъю, яюЄюьє ўЄю ьхцфє ьюфхы ьш └╥╠2 юэш эх ьхэ ■Єё .
  27.     const int tScanlineWidth = 224;
  28.     const int tScreenWidth = 320/2;
  29.     const int tEachBorderWidth = (tScanlineWidth - tScreenWidth)/2;
  30.     const int iLinesAboveBorder = 56;
  31.  
  32.     int iRayLine = cpu.t / tScanlineWidth;
  33.     int iRayOffset = cpu.t % tScanlineWidth;
  34. /*    
  35.     static int iLastLine = 0;
  36.     if ( iLastLine > iRayLine )
  37.     {
  38.         printf("\nNew Frame Begin\n");
  39.         __debugbreak();
  40.     }
  41.     iLastLine = iRayLine;
  42.     printf("%d->%d %d %d\n", OldVideoMode, NewVideoMode, iRayLine, iRayOffset);
  43. */
  44.  
  45.     if (OldVideoMode == 3 || NewVideoMode == 3)
  46.     {
  47.         // ╧хЁхъы■ўхэшх шч/т sinclair Ёхцшь эх шьххЄ яюыхчэ√ї яюсюўэ√ї ¤ЇЇхъЄют
  48.         // (яю ёыютрь AlCo фрцх ёшэїЁр ёсштрхЄё )
  49.         for(unsigned y = 0; y < 200; y++)
  50.         {
  51.             AtmVideoCtrl.Scanlines[y+56].VideoMode = NewVideoMode;
  52.             AtmVideoCtrl.Scanlines[y+56].Offset = int(((y & ~7U) << 3) + 0x01C0);
  53.         }
  54.         return;
  55.     }
  56.  
  57.     if (OldVideoMode != 6 && NewVideoMode != 6)
  58.     {
  59.         // ═рё шэЄхЁхёє■Є Єюы№ъю яхЁхъы■ўхэш  ьхцфє ЄхъёЄют√ь Ёхцшьюь ш Ёрё°шЁхээ√ьш уЁрЇшўхёъшьш.
  60.         // ╥хъёЄютюую Ёхцшьр эхЄ эш фю, эш яюёых яхЁхъы■ўхэш .
  61.         // ╤ыхфютрЄхы№эю, эхЄ ш яюсюўэ√ї ¤ЇЇхъЄют.
  62.        
  63.         // ╨рёяЁюёЄЁрэ хь эют√щ тшфхюЁхцшь эр эхюЄЁшёютрээ√х ёърэышэшш
  64.         if (iRayOffset >= tEachBorderWidth)
  65.             ++iRayLine;
  66.  
  67.         while (iRayLine < 256)
  68.         {
  69.             AtmVideoCtrl.Scanlines[iRayLine++].VideoMode = NewVideoMode;
  70.         }
  71. //        printf("%d->%d SKIPPED!\n",  OldVideoMode, NewVideoMode);
  72.         return;
  73.     }
  74.  
  75.     //
  76.     // ╥хЁьшэюыюуш  ш ъюэёЄрэЄ√:
  77.     // ▌ъЁрэ ёюфхЁцшЄ 312 ёърэышэшщ, яю 224ЄръЄр (noturbo) т ърцфющ.
  78.     //
  79.     //  "ёЄЁюър" - ьырф°шх 3 сшЄр эюьхЁр юЄЁшёют√трхьющ тшфхюъюэЄЁюыыхЁюь (ыєўюь) ёърэышэшш
  80.     //  "рфЁхё"  - Єхъє∙шщ рфЁхё т тшфхюярь Єш, ё ъюЄюЁюую т√сшЁрхЄ срщЄ√ тшфхюъюэЄЁюыыхЁ
  81.     //             рфЁхё ьхэ хЄё  ё уЁрэєы ЁэюёЄ№■ +8 шыш +64
  82.     //  "¤ъЁрэ"  - ЁрёЄЁютр  ърЁЄшэър. ╤ю тёхї ёЄюЁюэ юъЁєцхэр "сюЁф■Ёюь".
  83.     //             ╨рчьхЁ√ сюЁф■Ёр:
  84.     //          ётхЁїє ш ёэшчє юЄ ЁрёЄЁр: 56 ёърэышэшщ
  85.     //              ёыхтр ш ёяЁртр юЄ ЁрёЄЁр: 32 ЄръЄр (64яшъёхы ).
  86.     //
  87.     // +64 яЁюшёїюфшЄ, ъюуфр CROW 1->0, Єю хёЄ№:
  88.     //  ышсю т ЄхъёЄьюфх яЁш яхЁхїюфх ёю ёЄЁюъш 7 эр ёЄЁюъє 0,
  89.     //  ышсю яЁш яхЁхъы■ўхэшш ЄхъёЄьюф->уЁрЇшър яЁш рфЁхёх A5=0,
  90.     //  ышсю яЁш яхЁхъы■ўхэшш уЁрЇшър->ЄхъёЄьюф яЁш рфЁхёх A5=1 ш ёЄЁюъх 0..3
  91.     //
  92.     // +8 яЁюшёїюфшЄ эр ЁрёЄЁх т ъюэЎх 64-сыюър яшъёхыхщ (ърцф√х 32ЄръЄр) эхчртшёшью юЄ Ёхцшьр
  93.     // (┬└╞═╬: +8 эх чртЁряыхэ√ тэєЄЁш A3..A5 р яЁюшчтюф Є ўхёЄэюх ёыюцхэшх ё рфЁхёюь.)
  94.     //
  95.     // ёсЁюё A3..A5 (эръюяыхээ√ї +8) яЁюшёїюфшЄ, ъюуфр RCOL 1->0, Єю хёЄ№:
  96.     //  ышсю т ЄхъёЄьюфх яЁш яхЁхїюфх ё ЁрёЄЁр эр сюЁф■Ё,
  97.     //  ышсю эр сюЁф■Ёх яЁш яхЁхъы■ўхэшш уЁрЇшър->ЄхъёЄьюф
  98.     //
  99.  
  100.  
  101.     if (iRayLine >= 256)
  102.     {
  103.         return;
  104.     }
  105.  
  106.     // ╧юыєўшь юЇЇёхЄ Єхъє∙хщ ёърэышэшш (ЇръЄшўхёъш тшфхюрфЁхё х╕ эрўрыр)
  107.     int Offset = AtmVideoCtrl.Scanlines[iRayLine].Offset;
  108.  
  109.     // ┬√ўшёышь Ёхры№э√щ тшфхюрфЁхё, ё єў╕Єюь шэъЁхьхэЄют яЁш юЄЁшёютъх ЁрёЄЁр.
  110.     // ╥ръцх юяЁхфхышь, ъєфр яЁшьхэ хь +64 шэъЁхьхэЄ√ яЁш яхЁхъы■ўхэшш тшфхюЁхцшьр:
  111.     //  - ┼ёыш ыєў эр сюЁф■Ёх ётхЁїє юЄ ЁрёЄЁр шыш эр сюЁф■Ёх ёыхтр юЄ ЁрёЄЁр - шчьхэ хь юЇЇёхЄ фы  Єхъє∙хщ ёърэышэшш
  112.     //  - ┼ёыш ыєў эр ЁрёЄЁх шыш эр сюЁф■Ёх ёяЁртр юЄ ЁрёЄЁр - шчьхэ хь юЇЇёхЄ фы  ёыхфє■∙хщ ёърэышэшш
  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.  
  301.    // ╧ЁхюсЁрчютрэшх ярышЄЁ√ т ЇюЁьрЄ ULA+
  302.    u8 PalIdx = ((comp.border_attr & 8) << 1) | (comp.border_attr & 7);
  303.    comp.comp_pal[PalIdx + 0*8] =
  304.    comp.comp_pal[PalIdx + 1*8] =
  305.    comp.comp_pal[PalIdx + 3*8] =
  306.    comp.comp_pal[PalIdx + 5*8] = u8(t.atm_pal_map[val]);
  307.    temp.comp_pal_changed = 1;
  308. }
  309.  
  310. u8 atm_readpal()
  311. {
  312.    return atm_pal[comp.border_attr];
  313. }
  314.  
  315. unsigned char atm450_z(unsigned t)
  316. {
  317.    // PAL hardware gives 3 zeros in secret short time intervals
  318.    if (conf.frame < 80000) { // NORMAL SPEED mode
  319.       if ((unsigned)(t-7200) < 40 || (unsigned)(t-7284) < 40 || (unsigned)(t-7326) < 40) return 0;
  320.    } else { // TURBO mode
  321.       if ((unsigned)(t-21514) < 40 || (unsigned)(t-21703) < 80 || (unsigned)(t-21808) < 40) return 0;
  322.    }
  323.    return 0x80;
  324. }
  325.