~ubuntu-branches/debian/sid/stella/sid

« back to all changes in this revision

Viewing changes to src/emucore/CartFA2.cxx

  • Committer: Package Import Robot
  • Author(s): Stephen Kitt
  • Date: 2012-06-02 07:33:16 UTC
  • mfrom: (1.1.15)
  • Revision ID: package-import@ubuntu.com-20120602073316-20r4hr32t4oj36u9
Tags: 3.7-1
* New upstream version.
* Update description and documentation with new features in 3.7, notably
  Blargg TV filters (replacing the filters available in versions 3.4.1
  and earlier).
* Switch to debhelper compatibility level 9.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
// See the file "License.txt" for information on usage and redistribution of
15
15
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16
16
//
17
 
// $Id: CartFA2.cxx 2435 2012-03-30 21:07:57Z stephena $
 
17
// $Id: CartFA2.cxx 2499 2012-05-25 12:41:19Z stephena $
18
18
//============================================================================
19
19
 
20
20
#include <cassert>
21
21
#include <cstring>
22
22
 
 
23
#include "OSystem.hxx"
 
24
#include "Serializer.hxx"
23
25
#include "System.hxx"
24
26
#include "CartFA2.hxx"
25
27
 
26
28
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
27
 
CartridgeFA2::CartridgeFA2(const uInt8* image, uInt32 size, const Settings& settings)
28
 
  : Cartridge(settings),
 
29
CartridgeFA2::CartridgeFA2(const uInt8* image, uInt32 size, const OSystem& osystem)
 
30
  : Cartridge(osystem.settings()),
 
31
    myOSystem(osystem),
 
32
    myRamAccessTimeout(0),
29
33
    mySize(size)
30
34
{
31
35
  // Allocate array for the ROM image
106
110
  // Switch banks if necessary
107
111
  switch(address)
108
112
  {
 
113
    case 0x0FF4:
 
114
      // Load/save RAM to/from Harmony cart flash
 
115
      if(mySize == 28*1024 && !bankLocked())
 
116
        return ramReadWrite();
 
117
      break;
 
118
 
109
119
    case 0x0FF5:
110
120
      // Set the current bank to the first 4k bank
111
121
      bank(0);
171
181
  // Switch banks if necessary
172
182
  switch(address)
173
183
  {
 
184
    case 0x0FF4:
 
185
      // Load/save RAM to/from Harmony cart flash
 
186
      if(mySize == 28*1024 && !bankLocked())
 
187
        ramReadWrite();
 
188
      break;
 
189
 
174
190
    case 0x0FF5:
175
191
      // Set the current bank to the first 4k bank
176
192
      bank(0);
231
247
  System::PageAccess access(0, 0, 0, this, System::PA_READ);
232
248
 
233
249
  // Set the page accessing methods for the hot spots
234
 
  for(uInt32 i = (0x1FF5 & ~mask); i < 0x2000; i += (1 << shift))
 
250
  for(uInt32 i = (0x1FF4 & ~mask); i < 0x2000; i += (1 << shift))
235
251
  {
236
252
    access.codeAccessBase = &myCodeAccessBase[offset + (i & 0x0FFF)];
237
253
    mySystem->setPageAccess(i >> shift, access);
238
254
  }
239
255
 
240
256
  // Setup the page access methods for the current bank
241
 
  for(uInt32 address = 0x1200; address < (0x1FF5U & ~mask);
 
257
  for(uInt32 address = 0x1200; address < (0x1FF4U & ~mask);
242
258
      address += (1 << shift))
243
259
  {
244
260
    access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
291
307
  try
292
308
  {
293
309
    out.putString(name());
294
 
    out.putInt(myCurrentBank);
295
 
 
296
 
    // The 256 bytes of RAM
297
 
    out.putInt(256);
298
 
    for(uInt32 i = 0; i < 256; ++i)
299
 
      out.putByte((char)myRAM[i]);
 
310
    out.putShort(myCurrentBank);
 
311
    out.putByteArray(myRAM, 256);
300
312
  }
301
 
  catch(const char* msg)
 
313
  catch(...)
302
314
  {
303
 
    cerr << "ERROR: CartridgeFA2::save" << endl << "  " << msg << endl;
 
315
    cerr << "ERROR: CartridgeFA2::save" << endl;
304
316
    return false;
305
317
  }
306
318
 
315
327
    if(in.getString() != name())
316
328
      return false;
317
329
 
318
 
    myCurrentBank = (uInt16) in.getInt();
319
 
 
320
 
    uInt32 limit = (uInt32) in.getInt();
321
 
    for(uInt32 i = 0; i < limit; ++i)
322
 
      myRAM[i] = (uInt8) in.getByte();
 
330
    myCurrentBank = in.getShort();
 
331
    in.getByteArray(myRAM, 256);
323
332
  }
324
 
  catch(const char* msg)
 
333
  catch(...)
325
334
  {
326
 
    cerr << "ERROR: CartridgeFA2::load" << endl << "  " << msg << endl;
 
335
    cerr << "ERROR: CartridgeFA2::load" << endl;
327
336
    return false;
328
337
  }
329
338
 
332
341
 
333
342
  return true;
334
343
}
 
344
 
 
345
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
346
void CartridgeFA2::setRomName(const string& name)
 
347
{
 
348
  myFlashFile = myOSystem.eepromDir() + name + "_flash.dat";
 
349
}
 
350
 
 
351
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
352
uInt8 CartridgeFA2::ramReadWrite()
 
353
{
 
354
  /* The following algorithm implements accessing Harmony cart flash
 
355
 
 
356
    1. Wait for an access to hotspot location $1FF4 (return 1 in bit 6
 
357
       while busy).
 
358
 
 
359
    2. Read byte 256 of RAM+ memory to determine the operation requested
 
360
       (1 = read, 2 = write).
 
361
 
 
362
    3. Save or load the entire 256 bytes of RAM+ memory to a file.
 
363
 
 
364
    4. Set byte 256 of RAM+ memory to zero to indicate success (will
 
365
       always happen in emulation).
 
366
 
 
367
    5. Return 0 (in bit 6) on the next access to $1FF4, if enough time has
 
368
       passed to complete the operation on a real system (0.5 ms for read,
 
369
       101 ms for write).
 
370
  */
 
371
 
 
372
  // First access sets the timer
 
373
  if(myRamAccessTimeout == 0)
 
374
  {
 
375
    // Remember when the first access was made
 
376
    myRamAccessTimeout = myOSystem.getTicks();
 
377
 
 
378
    // We go ahead and do the access now, and only return when a sufficient
 
379
    // amount of time has passed
 
380
    Serializer serializer(myFlashFile);
 
381
    if(serializer.isValid())
 
382
    {
 
383
      if(myRAM[255] == 1)       // read
 
384
      {
 
385
        try
 
386
        {
 
387
          serializer.getByteArray(myRAM, 256);
 
388
        }
 
389
        catch(...)
 
390
        {
 
391
          memset(myRAM, 0, 256);
 
392
        }
 
393
        myRamAccessTimeout += 500;  // Add 0.5 ms delay for read
 
394
      }
 
395
      else if(myRAM[255] == 2)  // write
 
396
      {
 
397
        try
 
398
        {
 
399
          serializer.putByteArray(myRAM, 256);
 
400
        }
 
401
        catch(...)
 
402
        {
 
403
          // Maybe add logging here that save failed?
 
404
          cerr << name() << ": ERROR saving score table" << endl;
 
405
        }
 
406
        myRamAccessTimeout += 101000;  // Add 101 ms delay for write
 
407
      }
 
408
    }
 
409
    // Bit 6 is 1, busy
 
410
    return myImage[(myCurrentBank << 12) + 0xFF4] | 0x40;
 
411
  }
 
412
  else
 
413
  {
 
414
    // Have we reached the timeout value yet?
 
415
    if(myOSystem.getTicks() >= myRamAccessTimeout)
 
416
    {
 
417
      myRamAccessTimeout = 0;  // Turn off timer
 
418
      myRAM[255] = 0;          // Successful operation
 
419
 
 
420
      // Bit 6 is 0, ready/success
 
421
      return myImage[(myCurrentBank << 12) + 0xFF4] & ~0x40;
 
422
    }
 
423
    else
 
424
      // Bit 6 is 1, busy
 
425
      return myImage[(myCurrentBank << 12) + 0xFF4] | 0x40;
 
426
  }
 
427
}