File: sp.c

package info (click to toggle)
libspectrum 1.5.0-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 3,156 kB
  • sloc: ansic: 22,793; sh: 4,154; perl: 461; makefile: 178
file content (127 lines) | stat: -rw-r--r-- 4,294 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* sp.c: Routines for handling .sp snapshots
   Copyright (c) 1998,2003 Philip Kendall

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

   Author contact information:

   E-mail: philip-fuse@shadowmagic.org.uk

*/

#include "config.h"

#include <string.h>

#include "internals.h"

static const size_t SP_HEADER_LENGTH = 37;

libspectrum_error
libspectrum_sp_read( libspectrum_snap *snap, const libspectrum_byte *buffer,
		     size_t length )
{
  libspectrum_error error;
  libspectrum_word start, memory_length, flags;
  libspectrum_byte *memory;

  /* Length must be at least 48K of RAM plus the 'trailer' */
  if( length < SP_HEADER_LENGTH ) {
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_CORRUPT,
      "libspectrum_sp_read: not enough bytes for .sp header"
    );
    return LIBSPECTRUM_ERROR_CORRUPT;
  }

  /* Check the signature */
  if( buffer[0] != 'S' || buffer[1] != 'P' ) {
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_SIGNATURE,
      "libspectrum_sp_read: 'SP' signature not present"
    );
    return LIBSPECTRUM_ERROR_SIGNATURE;
  }
  buffer += 2;

  memory_length = libspectrum_read_word( &buffer );
  start = libspectrum_read_word( &buffer );

  /* Check for overrun of 48K memory */
  if( start + (libspectrum_dword)memory_length > 0x10000 ) {
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_CORRUPT,
      "libspectrum_sp_read: memory dump extends beyond 0xffff"
    );
    return LIBSPECTRUM_ERROR_CORRUPT;
  }

  if( start + memory_length < 0x8000 ) {
    libspectrum_snap_set_machine( snap, LIBSPECTRUM_MACHINE_16 );
  } else {
    libspectrum_snap_set_machine( snap, LIBSPECTRUM_MACHINE_48 );
  }

  /* Note that `buffer' has been incremented by 6 above */
    
  libspectrum_snap_set_bc     ( snap, buffer[ 0] + buffer[ 1] * 0x100 );
  libspectrum_snap_set_de     ( snap, buffer[ 2] + buffer[ 3] * 0x100 );
  libspectrum_snap_set_hl     ( snap, buffer[ 4] + buffer[ 5] * 0x100 );
  libspectrum_snap_set_f      ( snap, buffer[ 6] );
  libspectrum_snap_set_a      ( snap, buffer[ 7] );
  libspectrum_snap_set_ix     ( snap, buffer[ 8] + buffer[ 9] * 0x100 );
  libspectrum_snap_set_iy     ( snap, buffer[10] + buffer[11] * 0x100 );
  libspectrum_snap_set_bc_    ( snap, buffer[12] + buffer[13] * 0x100 );
  libspectrum_snap_set_de_    ( snap, buffer[14] + buffer[15] * 0x100 );
  libspectrum_snap_set_hl_    ( snap, buffer[16] + buffer[17] * 0x100 );
  libspectrum_snap_set_f_     ( snap, buffer[18] );
  libspectrum_snap_set_a_     ( snap, buffer[19] );
  libspectrum_snap_set_r      ( snap, buffer[20] );
  libspectrum_snap_set_i      ( snap, buffer[21] );
  libspectrum_snap_set_sp     ( snap, buffer[22] + buffer[23] * 0x100 );
  libspectrum_snap_set_pc     ( snap, buffer[24] + buffer[25] * 0x100 );
  /* Bytes 32 and 33 not used */
  libspectrum_snap_set_out_ula( snap, buffer[28] );
  /* Byte 35 not used */

  buffer += 30;

  flags = libspectrum_read_word( &buffer );

  libspectrum_snap_set_iff1   ( snap,   flags & 0x01 );
  libspectrum_snap_set_iff2   ( snap, ( flags & 0x04 ) >> 2 );

  /* bit 3 1 | IM
     --------+---
         0 0 |  1
         0 1 |  2 
         1 - |  0 */

  libspectrum_snap_set_im( snap,
			   ( flags & 0x08 ? 0 : ( flags & 0x02 ? 2 : 1 ) ) );

  /* Get me 48K of zero-ed memory and then copy in the bits that were
     represented in the snap */
  memory = libspectrum_new0( libspectrum_byte, 0xc000 );

  memcpy( &memory[ start ], buffer, memory_length );

  error = libspectrum_split_to_48k_pages( snap, memory );
  if( error ) { libspectrum_free( memory ); return error; }

  libspectrum_free( memory );

  return LIBSPECTRUM_ERROR_NONE;
}