?login_element?

Subversion Repositories NedoOS

Rev

Rev 129 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download

  1. /*
  2.  
  3.   SjASMPlus Z80 Cross Assembler
  4.  
  5.   Copyright (c) 2004-2008 Aprisobal
  6.  
  7.   This software is provided 'as-is', without any express or implied warranty.
  8.   In no event will the authors be held liable for any damages arising from the
  9.   use of this software.
  10.  
  11.   Permission is granted to anyone to use this software for any purpose,
  12.   including commercial applications, and to alter it and redistribute it freely,
  13.   subject to the following restrictions:
  14.  
  15.   1. The origin of this software must not be misrepresented; you must not claim
  16.          that you wrote the original software. If you use this software in a product,
  17.          an acknowledgment in the product documentation would be appreciated but is
  18.          not required.
  19.  
  20.   2. Altered source versions must be plainly marked as such, and must not be
  21.          misrepresented as being the original software.
  22.  
  23.   3. This notice may not be removed or altered from any source distribution.
  24.  
  25. */
  26.  
  27. // io_snapshots.cpp
  28.  
  29. #include "sjdefs.h"
  30.  
  31. // report error and close the file
  32. static int writeError(char* fname, FILE* & fileToClose) {
  33.         Error("Write error (disk full?)", fname, IF_FIRST);
  34.         fclose(fileToClose);
  35.         return 0;
  36. }
  37.  
  38. int SaveSNA_ZX(char* fname, unsigned short start) {
  39.         unsigned char snbuf[31];
  40.  
  41.         // for Lua
  42.         if (!DeviceID) {
  43.                 Error("[SAVESNA] Only for real device emulation mode.");
  44.                 return 0;
  45.         } else if (!IsZXSpectrumDevice(DeviceID)) {
  46.                 Error("[SAVESNA] Device must be ZXSPECTRUM48 or ZXSPECTRUM128.");
  47.                 return 0;
  48.         }
  49.  
  50.         FILE* ff;
  51.         if (!FOPEN_ISOK(ff, fname, "wb")) {
  52.                 Error("Error opening file", fname, FATAL);
  53.         }
  54.  
  55.         memset(snbuf, 0, sizeof(snbuf));
  56.         snbuf[0] = 0x3F; //i
  57.         snbuf[1] = 0x58; //hl'
  58.         snbuf[2] = 0x27; //hl'
  59.         snbuf[3] = 0x9B; //de'
  60.         snbuf[4] = 0x36; //de'
  61.         snbuf[5] = 0x00; //bc'
  62.         snbuf[6] = 0x00; //bc'
  63.         snbuf[7] = 0x44; //af'
  64.         snbuf[8] = 0x00; //af'
  65.         snbuf[9] = 0x2B; //hl
  66.         snbuf[10] = 0x2D; //hl
  67.         snbuf[11] = 0xDC; //de
  68.         snbuf[12] = 0x5C; //de
  69.         snbuf[13] = start & 0xFF;               //bc
  70.         snbuf[14] = (start>>8) & 0xFF;  //bc
  71.         snbuf[15] = 0x3a; //iy
  72.         snbuf[16] = 0x5c; //iy
  73.         snbuf[17] = 0x3C; //ix
  74.         snbuf[18] = 0xFF; //ix
  75.         snbuf[21] = 0x54; //af
  76.         snbuf[22] = 0x00; //af
  77.         // check if default ZX-like stack was modified - if not, it will be used for snapshot
  78.         bool is48kSnap = !strcmp(DeviceID, "ZXSPECTRUM48");
  79.         bool defaultStack = true;
  80.         aint stackAdr = Device->ZxRamTop + 1 - sizeof(ZX_STACK_DATA);
  81.         for (aint ii = is48kSnap ? -2 : 0; ii < aint(sizeof(ZX_STACK_DATA)); ++ii) {
  82.                 // will check for 48k snap if there is `00 00` ahead of fake stack data
  83.                 const byte cmpValue = (0 <= ii) ? ZX_STACK_DATA[ii] : 0;
  84.                 CDeviceSlot* slot = Device->GetSlot(Device->GetSlotOfA16(stackAdr + ii));
  85.                 CDevicePage* page = Device->GetPage(slot->InitialPage);
  86.                 defaultStack &= (cmpValue == page->RAM[(stackAdr + ii) & (page->Size-1)]);
  87.         }
  88.         if (defaultStack) {
  89.                 if (is48kSnap) stackAdr -= 2;
  90.                 snbuf[23] = (stackAdr) & 0xFF;  // SP (may point to injected start address for 48k snap)
  91.                 snbuf[24] = (stackAdr>>8) & 0xFF;
  92.                 if (is48kSnap) {
  93.                         // inject PC under default stack
  94.                         CDeviceSlot* slot = Device->GetSlot(Device->GetSlotOfA16(stackAdr));
  95.                         CDevicePage* page = Device->GetPage(slot->InitialPage);
  96.                         page->RAM[stackAdr & (page->Size-1)] = start & 0xFF;
  97.                         ++stackAdr;
  98.                         slot = Device->GetSlot(Device->GetSlotOfA16(stackAdr));
  99.                         page = Device->GetPage(slot->InitialPage);
  100.                         page->RAM[stackAdr & (page->Size-1)] = (start>>8) & 0xFF;
  101.                 }
  102.         } else {
  103.                 if (is48kSnap) {
  104.                         Warning("[SAVESNA] RAM <0x4000-0x4001> will be overriden due to 48k snapshot imperfect format.");
  105.                         snbuf[23] = 0x00; //sp
  106.                         snbuf[24] = 0x40; //sp
  107.                         Device->GetPage(1)->RAM[0] = start & 0xFF;      //pc
  108.                         Device->GetPage(1)->RAM[1] = start >> 8;        //pc
  109.                 } else {
  110.                         snbuf[23] = 0x00; //sp
  111.                         snbuf[24] = 0x60; //sp
  112.                 }
  113.         }
  114.         snbuf[25] = 1; //im 1
  115.         snbuf[26] = 7; //border 7
  116.  
  117.         if (fwrite(snbuf, 1, sizeof(snbuf) - 4, ff) != sizeof(snbuf) - 4) {
  118.                 return writeError(fname, ff);
  119.         }
  120.  
  121.         if (is48kSnap) {
  122.                 if ((aint) fwrite(Device->GetPage(1)->RAM, 1, Device->GetPage(1)->Size, ff) != Device->GetPage(1)->Size) {
  123.                         return writeError(fname, ff);
  124.                 }
  125.                 if ((aint) fwrite(Device->GetPage(2)->RAM, 1, Device->GetPage(2)->Size, ff) != Device->GetPage(2)->Size) {
  126.                         return writeError(fname, ff);
  127.                 }
  128.                 if ((aint) fwrite(Device->GetPage(3)->RAM, 1, Device->GetPage(3)->Size, ff) != Device->GetPage(3)->Size) {
  129.                         return writeError(fname, ff);
  130.                 }
  131.         } else {
  132.                 if ((aint) fwrite(Device->GetPage(5)->RAM, 1, Device->GetPage(5)->Size, ff) != Device->GetPage(5)->Size) {
  133.                         return writeError(fname, ff);
  134.                 }
  135.                 if ((aint) fwrite(Device->GetPage(2)->RAM, 1, Device->GetPage(2)->Size, ff) != Device->GetPage(2)->Size) {
  136.                         return writeError(fname, ff);
  137.                 }
  138.                 if ((aint) fwrite(Device->GetPage(Device->GetSlot(3)->Page->Number)->RAM, 1, Device->GetPage(0)->Size, ff) != Device->GetPage(0)->Size) {
  139.                         return writeError(fname, ff);
  140.                 }
  141.                 // 128k snapshot extra header fields
  142.                 snbuf[27] = char(start & 0x00FF); //pc
  143.                 snbuf[28] = char(start >> 8); //pc
  144.                 snbuf[29] = 0x10 + Device->GetSlot(3)->Page->Number; //7ffd
  145.                 snbuf[30] = 0; //tr-dos
  146.                 if (fwrite(snbuf + 27, 1, 4, ff) != 4) {
  147.                         return writeError(fname, ff);
  148.                 }
  149.                 // 128k banks
  150.                 for (aint i = 0; i < 8; i++) {
  151.                         if (i != Device->GetSlot(3)->Page->Number && i != 2 && i != 5) {
  152.                                 if ((aint) fwrite(Device->GetPage(i)->RAM, 1, Device->GetPage(i)->Size, ff) != Device->GetPage(i)->Size) {
  153.                                         return writeError(fname, ff);
  154.                                 }
  155.                         }
  156.                 }
  157.         }
  158.  
  159.         if (128*1024 < Device->PagesCount * Device->GetPage(0)->Size) {
  160.                 Warning("Only 128kb will be written to snapshot", fname);
  161.         }
  162.  
  163.         fclose(ff);
  164.         return 1;
  165. }
  166.  
  167. //eof io_snapshots.cpp
  168.