Hi,

I've had a go at implementing SAM Messenger snapshot loading support for
libspectrum (I.e. FUSE).

It seems to work, but needs more testing.  There was one snapshot that
I couldn't get working, but I've no idea why... perhaps a timing issue?

Anyway, I've included a disassembly of the messenger loader as well as
the diff against libspectrum.

Cheers,
-- 
Stuart Brady

; mesload.asm
08ed:   di
        ld (8938),sp ; 0938
        in a,(fc) ; vmpr
        ld (8937),a  ; 0937
        in a,(fa) ; lmpr
        ld (8935),a  ; 0935

        ld a,04
        out (fc),a ; vmpr

        ld sp,bcea  ; 3cea
        pop iy  ; restore iy
        pop ix  ; restore ix
        pop de  ; restore de'
        pop bc  ; restore bc'
        pop hl  ; restore hl'
        pop af  ; restore af'
        exx
        ex af,af'
        pop de  ; restore de
        pop bc  ; restore bc
        pop hl  ; restore hl

        pop af  ; restore i
        ld i,a
        cp 3f   ; set interrupt mode...
        jr z,ldstk
        cp 00
        jr z,ldstk
        im 2

ldstk:  ld sp,(bcfe) ; restore sp
        ld a,a3    ; wpram | rom0 | bcd 3
        out (fa),a ; lmpr
        jp 0928    ; ???
        ld a,05    ; bcd 5
0928:   out (fb),a ; hmpr

        pop af
        ld r,a     ; restore r
        jp po,0933 ; check bit 2 of f, skip if zero
        ei

0933:   pop af     ; restore af
        ret        ; restore pc

; note that sp has been incremented by 6 since it was loaded



diff -urN libspectrum.orig/internals.h libspectrum.messenger/internals.h
--- libspectrum.orig/internals.h        2006-01-21 04:49:19.000000000 +0000
+++ libspectrum.messenger/internals.h   2006-01-21 00:49:31.000000000 +0000
@@ -123,6 +123,9 @@
 libspectrum_plusd_read( libspectrum_snap *snap,
                        const libspectrum_byte *buffer, size_t buffer_length );
 libspectrum_error
+libspectrum_mes_read( libspectrum_snap *snap,
+                     const libspectrum_byte *buffer, size_t buffer_length );
+libspectrum_error
 internal_sna_read( libspectrum_snap *snap,
                   const libspectrum_byte *buffer, size_t buffer_length );
 libspectrum_error
diff -urN libspectrum.orig/libspectrum.c libspectrum.messenger/libspectrum.c
--- libspectrum.orig/libspectrum.c      2006-01-21 04:49:34.000000000 +0000
+++ libspectrum.messenger/libspectrum.c 2006-01-21 00:45:27.000000000 +0000
@@ -450,6 +450,7 @@
       
       { LIBSPECTRUM_ID_RECORDING_RZX, "rzx", 3, "RZX!",                    0, 
4, 4 },
 
+      { LIBSPECTRUM_ID_SNAPSHOT_MES,  "mes", 3, NULL,              0, 0, 0 },
       { LIBSPECTRUM_ID_SNAPSHOT_SNA,  "sna", 3, NULL,              0, 0, 0 },
       { LIBSPECTRUM_ID_SNAPSHOT_SNP,  "snp", 3, NULL,              0, 0, 0 },
       { LIBSPECTRUM_ID_SNAPSHOT_SP,   "sp",  3, "\x53\x50\0",      0, 3, 1 },
@@ -559,6 +560,7 @@
     *libspectrum_class = LIBSPECTRUM_CLASS_RECORDING; return 0;
 
   case LIBSPECTRUM_ID_SNAPSHOT_PLUSD:
+  case LIBSPECTRUM_ID_SNAPSHOT_MES:
   case LIBSPECTRUM_ID_SNAPSHOT_SNA:
   case LIBSPECTRUM_ID_SNAPSHOT_SNP:
   case LIBSPECTRUM_ID_SNAPSHOT_SP:
diff -urN libspectrum.orig/libspectrum.h.in 
libspectrum.messenger/libspectrum.h.in
--- libspectrum.orig/libspectrum.h.in   2006-01-21 04:49:34.000000000 +0000
+++ libspectrum.messenger/libspectrum.h.in      2006-01-21 00:42:01.000000000 
+0000
@@ -149,6 +149,7 @@
   LIBSPECTRUM_ID_SNAPSHOT_SNP,         /* .snp snapshot */
   LIBSPECTRUM_ID_SNAPSHOT_ZXS,         /* .zxs snapshot (zx32) */
   LIBSPECTRUM_ID_SNAPSHOT_SZX,         /* .szx snapshot (Spectaculator) */
+  LIBSPECTRUM_ID_SNAPSHOT_MES,         /* .mes snapshot (Messenger) */
 
   /* Below here, present only in 0.2.1 and later */
 
diff -urN libspectrum.orig/Makefile.am libspectrum.messenger/Makefile.am
--- libspectrum.orig/Makefile.am        2006-01-21 04:49:33.000000000 +0000
+++ libspectrum.messenger/Makefile.am   2006-01-20 23:53:21.000000000 +0000
@@ -32,6 +32,7 @@
                         dck.c \
                         ide.c \
                         libspectrum.c \
+                        mes.c \
                         microdrive.c \
                         plusd.c \
                         rzx.c \
diff -urN libspectrum.orig/mes.c libspectrum.messenger/mes.c
--- libspectrum.orig/mes.c      1970-01-01 01:00:00.000000000 +0100
+++ libspectrum.messenger/mes.c 2006-01-21 04:16:37.000000000 +0000
@@ -0,0 +1,89 @@
+/* mes.c: Routines for handling SAM Coupe Messenger snapshots
+   Copyright (c) 2006 Stuart Brady
+   Copyright (c) 1998,2003 Philip Kendall
+
+   $Id$
+
+   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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+   Author contact information:
+
+   E-mail: [EMAIL PROTECTED]
+   Postal address: 15 Crescent Road, Wokingham, Berks, RG40 2DB, England
+
+*/
+
+#include <config.h>
+
+#include "internals.h"
+
+libspectrum_error
+libspectrum_mes_read( libspectrum_snap *snap, const libspectrum_byte *buffer,
+                     size_t length )
+{
+  libspectrum_error error;
+  const libspectrum_byte *regs;
+  libspectrum_word sp;
+  libspectrum_byte i;
+
+  /* Length must be at least 64K (48K RAM with 16K ROM image) */
+  if( length < 0x10000 ) {
+    libspectrum_print_error(
+      LIBSPECTRUM_ERROR_CORRUPT,
+      "libspectrum_mes_read: not enough bytes for a .mes file"
+    );
+    return LIBSPECTRUM_ERROR_CORRUPT;
+  }
+
+  /* All Messenger snaps are of the 48K machine */
+  libspectrum_snap_set_machine( snap, LIBSPECTRUM_MACHINE_48 );
+
+  /* Get the RAM */
+  error = libspectrum_split_to_48k_pages( snap, buffer + 0x4000 );
+  if( error != LIBSPECTRUM_ERROR_NONE ) return error;
+
+  regs = buffer + 0x3cea; /* register offset */
+  libspectrum_snap_set_iy     ( snap, regs[ 0] + regs[ 1] * 0x100 );
+  libspectrum_snap_set_ix     ( snap, regs[ 2] + regs[ 3] * 0x100 );
+  libspectrum_snap_set_de_    ( snap, regs[ 4] + regs[ 5] * 0x100 );
+  libspectrum_snap_set_bc_    ( snap, regs[ 6] + regs[ 7] * 0x100 );
+  libspectrum_snap_set_hl_    ( snap, regs[ 8] + regs[ 9] * 0x100 );
+  libspectrum_snap_set_f_     ( snap, regs[10] );
+  libspectrum_snap_set_a_     ( snap, regs[11] );
+  libspectrum_snap_set_de     ( snap, regs[12] + regs[13] * 0x100 );
+  libspectrum_snap_set_bc     ( snap, regs[14] + regs[15] * 0x100 );
+  libspectrum_snap_set_hl     ( snap, regs[16] + regs[17] * 0x100 );
+
+  /* Byte 18 not used */
+  i = regs[19];
+  if (i == 00 || i == 0x3f) {
+    libspectrum_snap_set_im   ( snap, 0 );
+  } else {
+    libspectrum_snap_set_im   ( snap, 2 );
+  }
+  libspectrum_snap_set_i      ( snap, i );
+
+  sp = (regs[20] + regs[21] * 0x100) & 0xffff;
+  libspectrum_snap_set_sp     ( snap, (sp + 6) & 0xffff );
+
+  libspectrum_snap_set_iff1   ( snap, buffer[sp + 0] & 0x02 ? 0 : 1 );
+  libspectrum_snap_set_iff2   ( snap, 0 );
+  libspectrum_snap_set_r      ( snap, buffer[sp + 1] );
+  libspectrum_snap_set_f      ( snap, buffer[sp + 2] );
+  libspectrum_snap_set_a      ( snap, buffer[sp + 3] );
+  libspectrum_snap_set_pc     ( snap, buffer[sp + 4] + buffer[sp + 5] * 0x100 
);
+
+  return LIBSPECTRUM_ERROR_NONE;
+}
diff -urN libspectrum.orig/snapshot.c libspectrum.messenger/snapshot.c
--- libspectrum.orig/snapshot.c 2006-01-21 04:49:19.000000000 +0000
+++ libspectrum.messenger/snapshot.c    2006-01-21 00:46:20.000000000 +0000
@@ -224,6 +224,9 @@
   case LIBSPECTRUM_ID_SNAPSHOT_PLUSD:
     error = libspectrum_plusd_read( snap, buffer, length ); break;
 
+  case LIBSPECTRUM_ID_SNAPSHOT_MES:
+    error = libspectrum_mes_read( snap, buffer, length ); break;
+
   case LIBSPECTRUM_ID_SNAPSHOT_SNA:
     error = internal_sna_read( snap, buffer, length ); break;

Reply via email to