From 1d83233ef2f233ade2ac53355fd3af7a1b481898 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Tue, 18 Feb 2014 13:33:33 +0100 Subject: [PATCH] - support for FDD3000, taken from fdd3000e - rel 6 --- fuse-1.1.1.patch | 881 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 881 insertions(+) create mode 100644 fuse-1.1.1.patch diff --git a/fuse-1.1.1.patch b/fuse-1.1.1.patch new file mode 100644 index 0000000..4c514c7 --- /dev/null +++ b/fuse-1.1.1.patch @@ -0,0 +1,881 @@ +diff -Naru fuse-1.1.1/fuse.c fuse-1.1.1.fdd3000/fuse.c +--- fuse-1.1.1/fuse.c 2013-05-16 22:26:23.000000000 +0200 ++++ fuse-1.1.1.fdd3000/fuse.c 2014-02-14 08:28:21.228997802 +0100 +@@ -274,6 +274,7 @@ + rzx_init(); + psg_init(); + beta_init(); ++ tim397_init(); + opus_init(); + plusd_init(); + disciple_init(); +diff -Naru fuse-1.1.1/machines/machines_periph.c fuse-1.1.1.fdd3000/machines/machines_periph.c +--- fuse-1.1.1/machines/machines_periph.c 2013-05-16 22:26:11.000000000 +0200 ++++ fuse-1.1.1.fdd3000/machines/machines_periph.c 2014-02-14 08:30:34.228014927 +0100 +@@ -201,6 +201,7 @@ + periph_set_present( PERIPH_TYPE_FULLER, PERIPH_PRESENT_OPTIONAL ); + periph_set_present( PERIPH_TYPE_ZXPRINTER, PERIPH_PRESENT_OPTIONAL ); + periph_set_present( PERIPH_TYPE_DISCIPLE, PERIPH_PRESENT_OPTIONAL ); ++ periph_set_present( PERIPH_TYPE_TIM397, PERIPH_PRESENT_OPTIONAL ); + } + + /* The set of peripherals available on the 128K and similar machines */ +diff -Naru fuse-1.1.1/Makefile.in fuse-1.1.1.fdd3000/Makefile.in +--- fuse-1.1.1/Makefile.in 2013-05-30 00:21:33.000000000 +0200 ++++ fuse-1.1.1.fdd3000/Makefile.in 2014-02-14 08:33:02.997237928 +0100 +@@ -232,7 +232,7 @@ + LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ + LIBOBJS = @LIBOBJS@ + LIBPNG_CONFIG = @LIBPNG_CONFIG@ +-LIBS = @LIBS@ ++LIBS = @LIBS@ -lrt + LIBSPEC_CFLAGS = @LIBSPEC_CFLAGS@ + LIBSPEC_HAVE_AUDIOFILE = @LIBSPEC_HAVE_AUDIOFILE@ + LIBSPEC_HAVE_BZ2 = @LIBSPEC_HAVE_BZ2@ +diff -Naru fuse-1.1.1/memory.c fuse-1.1.1.fdd3000/memory.c +--- fuse-1.1.1/memory.c 2013-05-16 22:26:23.000000000 +0200 ++++ fuse-1.1.1.fdd3000/memory.c 2014-02-14 08:21:36.769616238 +0100 +@@ -37,6 +37,7 @@ + #include "memory.h" + #include "module.h" + #include "peripherals/disk/opus.h" ++#include "peripherals/disk/ti_m397.h" + #include "peripherals/spectranet.h" + #include "peripherals/ula.h" + #include "settings.h" +diff -Naru fuse-1.1.1/menu.c fuse-1.1.1.fdd3000/menu.c +--- fuse-1.1.1/menu.c 2013-05-16 22:26:23.000000000 +0200 ++++ fuse-1.1.1.fdd3000/menu.c 2014-02-14 08:21:36.769616238 +0100 +@@ -36,6 +36,7 @@ + #include "peripherals/disk/beta.h" + #include "peripherals/disk/disciple.h" + #include "peripherals/disk/opus.h" ++#include "peripherals/disk/ti_m397.h" + #include "peripherals/disk/plusd.h" + #include "peripherals/ide/divide.h" + #include "peripherals/ide/simpleide.h" +@@ -224,7 +225,8 @@ + case 18: menu_select_roms_with_title( "+D", 42, 1 ); return; + case 19: menu_select_roms_with_title( "DISCiPLE", 43, 1 ); return; + case 20: menu_select_roms_with_title( "Opus Discovery", 44, 1 ); return; +- case 21: menu_select_roms_with_title( "SpeccyBoot", 45, 1 ); return; ++ case 21: menu_select_roms_with_title( "Timex M397", 45, 1 ); return; ++ case 22: menu_select_roms_with_title( "SpeccyBoot", 46, 1 ); return; + + } + +diff -Naru fuse-1.1.1/menu_data.dat fuse-1.1.1.fdd3000/menu_data.dat +--- fuse-1.1.1/menu_data.dat 2013-05-16 22:26:23.000000000 +0200 ++++ fuse-1.1.1.fdd3000/menu_data.dat 2014-02-14 08:21:36.769616238 +0100 +@@ -101,7 +101,8 @@ + Options/Select ROMs/+_D..., Item,, menu_options_selectroms_select,, 18 + Options/Select ROMs/DISCiP_LE..., Item,, menu_options_selectroms_select,, 19 + Options/Select ROMs/_Opus Discovery..., Item,, menu_options_selectroms_select,, 20 +-Options/Select ROMs/Specc_yBoot..., Item,, menu_options_selectroms_select,, 21 ++Options/Select ROMs/_Timex M397..., Item,, menu_options_selectroms_select,, 21 ++Options/Select ROMs/Specc_yBoot..., Item,, menu_options_selectroms_select,, 22 + + Options/_Filter..., Item,,, menu_filter_detail + +diff -Naru fuse-1.1.1/peripherals/disk/Makefile.am fuse-1.1.1.fdd3000/peripherals/disk/Makefile.am +--- fuse-1.1.1/peripherals/disk/Makefile.am 2013-05-16 22:26:03.000000000 +0200 ++++ fuse-1.1.1.fdd3000/peripherals/disk/Makefile.am 2014-02-14 08:21:36.769616238 +0100 +@@ -37,6 +37,7 @@ + opus.c \ + plusd.c \ + upd_fdc.c \ ++ ti_m397.c \ + wd_fdc.c + + noinst_HEADERS = beta.h \ +@@ -47,4 +48,5 @@ + opus.h \ + plusd.h \ + upd_fdc.h \ ++ ti_m397.h \ + wd_fdc.h +diff -Naru fuse-1.1.1/peripherals/disk/Makefile.in fuse-1.1.1.fdd3000/peripherals/disk/Makefile.in +--- fuse-1.1.1/peripherals/disk/Makefile.in 2013-05-24 22:56:08.000000000 +0200 ++++ fuse-1.1.1.fdd3000/peripherals/disk/Makefile.in 2014-02-14 08:32:46.900294664 +0100 +@@ -75,7 +75,7 @@ + libdisk_a_LIBADD = + am_libdisk_a_OBJECTS = beta.$(OBJEXT) crc.$(OBJEXT) disciple.$(OBJEXT) \ + disk.$(OBJEXT) fdd.$(OBJEXT) opus.$(OBJEXT) plusd.$(OBJEXT) \ +- upd_fdc.$(OBJEXT) wd_fdc.$(OBJEXT) ++ upd_fdc.$(OBJEXT) ti_m397.$(OBJEXT) wd_fdc.$(OBJEXT) + libdisk_a_OBJECTS = $(am_libdisk_a_OBJECTS) + DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) + depcomp = $(SHELL) $(top_srcdir)/depcomp +@@ -281,6 +281,7 @@ + opus.c \ + plusd.c \ + upd_fdc.c \ ++ ti_m397.c \ + wd_fdc.c + + noinst_HEADERS = beta.h \ +@@ -291,6 +292,7 @@ + opus.h \ + plusd.h \ + upd_fdc.h \ ++ ti_m397.h \ + wd_fdc.h + + all: all-am +@@ -349,6 +351,7 @@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opus.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plusd.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upd_fdc.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ti_m397.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wd_fdc.Po@am__quote@ + + .c.o: +diff -Naru fuse-1.1.1/peripherals/disk/ti_m397.c fuse-1.1.1.fdd3000/peripherals/disk/ti_m397.c +--- fuse-1.1.1/peripherals/disk/ti_m397.c 1970-01-01 01:00:00.000000000 +0100 ++++ fuse-1.1.1.fdd3000/peripherals/disk/ti_m397.c 2014-02-14 08:53:54.159789884 +0100 +@@ -0,0 +1,562 @@ ++/****************************************************************************** ++ This file is a part od FDD3000 Emulator ++ ++ Copyright (C) 2013 by Sławomir Szczyrba ++ Copyright (C) 2014 by Stefano Bodrato ++ ++ This program is free software: you can redistribute it and/or modify it under ++ the terms of the GNU Lesser 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 Lesser General Public License for more ++ details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this program. If not, see ++******************************************************************************/ ++ ++ ++#include ++ ++#include ++ ++#include ++ ++#include "compat.h" ++#include "machine.h" ++#include "module.h" ++#include "ti_m397.h" ++#include "peripherals/printer.h" ++#include "settings.h" ++#include "ui/ui.h" ++#include "unittests/unittests.h" ++//#include "utils.h" ++#include "wd_fdc.h" ++#include "options.h" /* needed for get combo options */ ++#include "z80/z80.h" ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include /* For mode constants */ ++#include ++#include ++ ++ ++#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__) ++ ++#include ++#include ++ ++#else ++ ++#include ++#ifndef SEM_FAILED ++#define SEM_FAILED -1 ++#endif ++#include ++#include ++#include ++#include ++ ++#endif ++ ++ ++ ++/* IPC */ ++ ++typedef struct tFdd2TiLink { ++ uint8_t fdd2ti; ++ uint8_t ti2fdd; ++ uint8_t fddAlive; ++ uint8_t tiAlive; ++} fdd2TiLink; ++ ++fdd2TiLink * fddlink; ++ ++ ++uint8_t data; ++int ipc, connected; ++char * path; ++ ++ ++ ++#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__) ++ ++HANDLE fdd2tiF, fdd2tiE, ti2fddF, ti2fddE, fddAlive; ++HANDLE shm, shmf; ++DWORD dwRetVal = 0; ++ ++TCHAR *shmId = _T("\\fdd.data"); ++//TCHAR shmId[]=TEXT("Global\\fdd.data"); ++TCHAR szTempFileName[MAX_PATH]; ++TCHAR lpTempPathBuffer[MAX_PATH]; ++ ++TCHAR fdd2tiE_Id[]=TEXT("Global\\fdd.fdd2ti.empty"); ++TCHAR fdd2tiF_Id[]=TEXT("Global\\fdd.fdd2ti.full"); ++TCHAR ti2fddE_Id[]=TEXT("Global\\fdd.ti2fdd.empty"); ++TCHAR ti2fddF_Id[]=TEXT("Global\\fdd.ti2fdd.full"); ++TCHAR fddAlive_Id[]=TEXT("Global\\fdd.alive"); ++/* ++TCHAR * fddAlive_Id = "fdd.alive"; ++TCHAR * fdd2tiE_Id = "fdd.fdd2ti.empty"; ++TCHAR * fdd2tiF_Id = "fdd.fdd2ti.full"; ++TCHAR * ti2fddE_Id = "fdd.ti2fdd.empty"; ++TCHAR * ti2fddF_Id = "fdd.ti2fdd.full"; ++*/ ++#else ++ ++sem_t *fdd2tiF,*fdd2tiE,*ti2fddF,*ti2fddE,*fddAlive; ++int shm; ++const char * shmId = "fdd.data"; ++ ++const char * fddAlive_Id = "fdd.alive"; ++const char * fdd2tiE_Id = "fdd.fdd2ti.empty"; ++const char * fdd2tiF_Id = "fdd.fdd2ti.full"; ++const char * ti2fddE_Id = "fdd.ti2fdd.empty"; ++const char * ti2fddF_Id = "fdd.ti2fdd.full"; ++ ++#endif ++ ++int8_t fddRead() { ++ uint8_t data=0; ++#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__) ++ WaitForSingleObject(ti2fddF,INFINITE); ++ data=fddlink->fdd2ti; ++ ReleaseSemaphore(ti2fddE,1,NULL); ++#else ++ sem_wait(fdd2tiF); ++ data=fddlink->fdd2ti; ++ sem_post(fdd2tiE); ++#endif ++ return data; ++} ++ ++void fddWrite(int8_t d) { ++#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__) ++ WaitForSingleObject(ti2fddE,INFINITE); ++ fddlink->ti2fdd=d; ++ ReleaseSemaphore(ti2fddF,1,NULL); ++#else ++ sem_wait(ti2fddE); ++ fddlink->ti2fdd=d; ++ sem_post(ti2fddF); ++#endif ++} ++ ++uint8_t fddIsAlive() { ++ uint8_t ok; ++#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__) ++ WaitForSingleObject(fddAlive,INFINITE); ++ ok=fddlink->fddAlive&fddlink->tiAlive; ++ ReleaseSemaphore(fddAlive,1,NULL); ++#else ++ sem_wait(fddAlive); ++ ok=fddlink->fddAlive&fddlink->tiAlive; ++ sem_post(fddAlive); ++#endif ++ return ok; ++} ++ ++void cleanUp() { ++ int i; ++ if(!ipc) { return; } ++ ipc=0; ++ connected=0; ++ ++#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__) ++ ++ WaitForSingleObject(fddAlive,INFINITE); ++ fddlink->tiAlive=0; ++ i=fddlink->fddAlive; ++ ReleaseSemaphore(fddAlive,1,NULL); ++ ++// semResetAll(); ++ CloseHandle(fddAlive); ++ CloseHandle(ti2fddF); ++ CloseHandle(ti2fddE); ++ CloseHandle(fdd2tiF); ++ CloseHandle(fdd2tiE); ++ ++ UnmapViewOfFile(fddlink); ++ if(!i) { ++ CloseHandle(shm); ++ CloseHandle(shmf); ++ } ++ ++#else ++ ++ sem_wait(fddAlive); ++ fddlink->tiAlive=0; ++ i=fddlink->fddAlive; ++ sem_post(fddAlive); ++ ++// semResetAll(); ++ sem_close(fddAlive); ++ sem_close(ti2fddF); ++ sem_close(ti2fddE); ++ sem_close(fdd2tiF); ++ sem_close(fdd2tiE); ++ ++ munmap(fddlink,sizeof(fdd2TiLink)); ++ if(!i) { ++ sem_unlink(fdd2tiE_Id); ++ sem_unlink(fdd2tiF_Id); ++ sem_unlink(ti2fddE_Id); ++ sem_unlink(ti2fddF_Id); ++ sem_unlink(fddAlive_Id); ++ shm_unlink(shmId); ++ } ++ ++#endif ++ ++} ++ ++int openShm() { ++ int trunc; ++ if(!ipc) { ++#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__) ++ //shmfile=ev.value("TMP",ev.value("TEMP","."))+"\\fdd.data"; ++ ++ // Gets the temp path env string (no guarantee it's a valid path). ++ dwRetVal = GetTempPath(MAX_PATH, lpTempPathBuffer); // buffer for path ++ if (dwRetVal > MAX_PATH || (dwRetVal == 0)) ++ { ++// fprintf(stderr,"tim397_openShm: GetTempPath failed\n"); ++ return (-1); ++ } ++ snprintf(szTempFileName,MAX_PATH,"%s%s",lpTempPathBuffer,shmId); ++ ++ shmf = CreateFile(szTempFileName, GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL); ++ ++ if (shmf == INVALID_HANDLE_VALUE) ++ { ++ //ui_error( UI_ERROR_ERROR, "tim397_openShm: CreateFile failed\n"); ++ return (-1); ++ } ++ ++ shm = CreateFileMapping( ++ shmf,//INVALID_HANDLE_VALUE, // use paging file ++ NULL, // default security ++ PAGE_READWRITE, // read/write access ++ 0, // maximum object size (high-order DWORD) ++ 256, // maximum object size (low-order DWORD) ++ NULL);//TEXT("Global\\shmFdd")); // name of mapping object ++ if(shm==NULL){ ++ //ui_error( UI_ERROR_ERROR, "tim397_openShm: CreateFileMapping failed\n"); ++ CloseHandle(shmf); ++ return (-1); ++ } ++ //fddlink=(fdd2TiLink*)mmap(0,sizeof(fdd2TiLink),PROT_READ|PROT_WRITE,MAP_SHARED,shm,0); ++ fddlink = (fdd2TiLink*)MapViewOfFile(shm, // handle to map object ++ FILE_MAP_ALL_ACCESS, // read/write permission ++ 0, ++ 0, ++ sizeof(fdd2TiLink)); ++ if(fddlink==NULL){ ++ //ui_error( UI_ERROR_ERROR, "tim397_openShm: MapViewOfFile (mmap) failed\n"); ++ CloseHandle(shm); ++ CloseHandle(shmf); ++ return (-1); ++ } ++ ++ fdd2tiE=OpenSemaphore(SEMAPHORE_MODIFY_STATE|SYNCHRONIZE, TRUE, fdd2tiE_Id); ++ fdd2tiF=OpenSemaphore(SEMAPHORE_MODIFY_STATE|SYNCHRONIZE, TRUE, fdd2tiF_Id); ++ ti2fddE=OpenSemaphore(SEMAPHORE_MODIFY_STATE|SYNCHRONIZE, TRUE, ti2fddE_Id); ++ ti2fddF=OpenSemaphore(SEMAPHORE_MODIFY_STATE|SYNCHRONIZE, TRUE, ti2fddF_Id); ++ fddAlive=OpenSemaphore(SEMAPHORE_MODIFY_STATE|SYNCHRONIZE, TRUE, fddAlive_Id); ++ ++ if ((fdd2tiE==NULL) || (fdd2tiF==NULL) || ++ (ti2fddE==NULL) || (ti2fddF==NULL) || (fddAlive==NULL)) { ++ //ui_error( UI_ERROR_ERROR, "tim397_openShm: semaphore creation failed\n"); ++ return (-1); ++ } ++ ++#else ++ shm = shm_open(shmId, O_RDWR, 0666); ++ if (-1==shm) { ++ //ui_error( UI_ERROR_ERROR, "tim397_openShm: shm_open failed\n"); ++ return (-1); ++ } ++ trunc=ftruncate(shm,sizeof(fdd2TiLink)); ++ if (-1==trunc) { ++ //ui_error( UI_ERROR_ERROR, "tim397_openShm: ftruncate failed\n"); ++ return (-1); ++ } ++ fddlink=(fdd2TiLink*)mmap(0,sizeof(fdd2TiLink),PROT_READ|PROT_WRITE,MAP_SHARED,shm,0); ++ if(fddlink==MAP_FAILED) { ++ //ui_error( UI_ERROR_ERROR, "tim397_openShm: mmap failed\n"); ++ return (-1); ++ } ++ close(shm); ++ ++ fdd2tiE=sem_open(fdd2tiE_Id,O_RDWR,0666,1); ++ fdd2tiF=sem_open(fdd2tiF_Id,O_RDWR,0666,0); ++ ti2fddE=sem_open(ti2fddE_Id,O_RDWR,0666,1); ++ ti2fddF=sem_open(ti2fddF_Id,O_RDWR,0666,0); ++ fddAlive=sem_open(fddAlive_Id,O_RDWR,0666,1); ++ if ((fdd2tiE==SEM_FAILED) || (fdd2tiF==SEM_FAILED) || ++ (ti2fddE==SEM_FAILED) || (ti2fddF==SEM_FAILED) || (fddAlive==SEM_FAILED)) { ++ //ui_error( UI_ERROR_ERROR, "tim397_openShm: semaphore creation failed\n"); ++ return (-1); ++ } ++#endif ++ ++ ipc=1; ++ } ++ if(ipc&&(!connected)) { ++#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__) ++ WaitForSingleObject(fddAlive,INFINITE); ++ if(fddlink->fddAlive){ fddlink->tiAlive=1; connected=1; } ++ ReleaseSemaphore(fddAlive,1,NULL); ++#else ++ sem_wait(fddAlive); ++ if(fddlink->fddAlive){ fddlink->tiAlive=1; connected=1; } ++ sem_post(fddAlive); ++#endif ++ } ++ return (0); ++} ++ ++ ++ ++/*************************************************************************/ ++ ++libspectrum_byte tim397_io_read( libspectrum_word port, int *attached ) { ++ libspectrum_byte b = 0; ++//ui_error( UI_ERROR_ERROR, "Reading from port: %u\n",port); ++ if(ipc&&connected) { ++//ui_error( UI_ERROR_ERROR, "Reading from port: %u\n",port); ++ if(fddIsAlive()) { b=fddRead(); } else { connected=0; /*semResetAll();*/ return 0; } ++ *attached = 1; ++ } ++ return b; ++} ++ ++void tim397_io_write( libspectrum_word port, libspectrum_byte b ) { ++//ui_error( UI_ERROR_ERROR, "Writing %u to port: %u\n",b,port); ++ if(ipc&&connected) { ++//ui_error( UI_ERROR_ERROR, "Writing %u to port: %u\n",b,port); ++// if ((port&&0xff) == 0xef) ++ if(fddIsAlive()) { fddWrite(b); } else { connected=0; /*semResetAll();*/ } ++ } ++} ++ ++/*************************************************************************/ ++ ++static void tim397_reset( int hard_reset ); ++static void tim397_memory_map( void ); ++static void tim397_enabled_snapshot( libspectrum_snap *snap ); ++static void tim397_from_snapshot( libspectrum_snap *snap ); ++static void tim397_to_snapshot( libspectrum_snap *snap ); ++static void tim397_activate( void ); ++ ++ ++/* Two 8Kb memory chunks accessible by the Z80 when /ROMCS is low */ ++static memory_page tim397_memory_map_romcs_rom[ MEMORY_PAGES_IN_8K ]; ++static memory_page tim397_memory_map_romcs_ram[ MEMORY_PAGES_IN_8K ]; ++static int tim397_memory_source; ++ ++int tim397_available = 0; ++int tim397_active = 0; ++ ++static libspectrum_byte *tim397_ram; ++static int memory_allocated = 0; ++ ++static module_info_t tim397_module_info = { ++ tim397_reset, ++ tim397_memory_map, ++ tim397_enabled_snapshot, ++ tim397_from_snapshot, ++ tim397_to_snapshot ++}; ++ ++void ++tim397_page( void ) ++{ ++ tim397_active = 1; ++ machine_current->ram.romcs = 1; ++ machine_current->memory_map(); ++ //ui_error( UI_ERROR_ERROR, "tim397_page, PC: $%x\n",m397_pageflag); ++ ui_statusbar_update( UI_STATUSBAR_ITEM_DISK, UI_STATUSBAR_STATE_ACTIVE ); ++} ++ ++void ++tim397_unpage( void ) ++{ ++ tim397_active = 0; ++ machine_current->ram.romcs = 0; ++ machine_current->memory_map(); ++ //ui_error( UI_ERROR_ERROR, "tim397_unpage, PC: $%x\n",z80.pc.w); ++ ui_statusbar_update( UI_STATUSBAR_ITEM_DISK, UI_STATUSBAR_STATE_INACTIVE ); ++} ++ ++static void ++tim397_memory_map( void ) ++{ ++ if( !tim397_active ) return; ++ memory_map_romcs_8k( 0x0000, tim397_memory_map_romcs_rom ); ++ memory_map_romcs_8k( 0x2000, tim397_memory_map_romcs_ram ); ++// ui_error( UI_ERROR_ERROR, "tim397_memory_map, PC: $%x\n",z80.pc.w); ++} ++ ++static const periph_port_t tim397_ports[] = { ++ { 0x00ff, 0x00ef, tim397_io_read, tim397_io_write }, ++ { 0, 0, NULL, NULL } ++}; ++ ++static const periph_t tim397_periph = { ++ &settings_current.ti_m397, ++ tim397_ports, ++ 1, ++ tim397_activate ++}; ++ ++int ++tim397_init( void ) ++{ ++ int i; ++ module_register( &tim397_module_info ); ++ ++ tim397_memory_source = memory_source_register( "TI_M397" ); ++ ++ for( i = 0; i < MEMORY_PAGES_IN_8K; i++ ) ++ tim397_memory_map_romcs_rom[ i ].source = tim397_memory_source; ++ for( i = 0; i < MEMORY_PAGES_IN_8K; i++ ) ++ tim397_memory_map_romcs_ram[ i ].source = tim397_memory_source; ++ ++ periph_register( PERIPH_TYPE_TIM397, &tim397_periph ); ++ ipc=0; ++ ++ fprintf(stderr,"tim397_init\n"); ++ ++ return 0; ++} ++ ++ ++static void ++tim397_reset( int hard_reset ) ++{ ++ ++ tim397_active = 0; ++ tim397_available = 0; ++ int i; ++ ++ if( !periph_is_active( PERIPH_TYPE_TIM397 ) ) { ++ ui_statusbar_update( UI_STATUSBAR_ITEM_DISK, ++ UI_STATUSBAR_STATE_NOT_AVAILABLE ); ++ return; ++ } ++ ++ if (openShm()!=0) { ++ settings_current.ti_m397 = 0; ++ periph_activate_type( PERIPH_TYPE_TIM397, 0 ); ++// ui_error( UI_ERROR_ERROR, "Link to FDD3000 emulator failed\n"); ++ return; ++ } ++ ++ if( machine_load_rom_bank( tim397_memory_map_romcs_rom, 0, ++ settings_current.rom_tim397, ++ settings_default.rom_tim397, 0x2000 ) ) { ++ settings_current.ti_m397 = 0; ++ periph_activate_type( PERIPH_TYPE_TIM397, 0 ); ++ ui_statusbar_update( UI_STATUSBAR_ITEM_DISK, ++ UI_STATUSBAR_STATE_NOT_AVAILABLE ); ++ return; ++ } ++ ++ machine_current->ram.romcs = 0; ++ ++ for( i = 0; i < MEMORY_PAGES_IN_8K; i++ ) { ++ tim397_memory_map_romcs_ram[ i ].page = &tim397_ram[ i * MEMORY_PAGE_SIZE ]; ++ tim397_memory_map_romcs_ram[ i ].writable = 1; ++ } ++ ++ tim397_available = 1; ++ tim397_active = 0; ++ ++ if( hard_reset ) { ++ memset( tim397_ram, 0, 0x2000 ); ++ } ++ ++ machine_current->memory_map(); ++ ui_statusbar_update( UI_STATUSBAR_ITEM_DISK, UI_STATUSBAR_STATE_INACTIVE ); ++ fprintf(stderr,"tim397_reset\n"); ++} ++ ++void ++tim397_end( void ) ++{ ++ tim397_available = 0; ++ ++ if(ipc&&connected) { ++#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__) ++ WaitForSingleObject(fddAlive,INFINITE); ++ fddlink->tiAlive=0; ++ ReleaseSemaphore(fddAlive,1,NULL); ++#else ++ sem_wait(fddAlive); ++ fddlink->tiAlive=0; ++ sem_post(fddAlive); ++#endif ++ } ++ ipc=0; ++ connected=0; ++ cleanUp(); ++ fprintf(stderr,"tim397_end\n"); ++} ++ ++static void ++tim397_activate( void ) ++{ ++ if( !memory_allocated ) { ++ tim397_ram = memory_pool_allocate_persistent( 0x2000, 1 ); ++ memory_allocated = 1; ++ } ++} ++ ++int ++tim397_unittest( void ) ++{ ++ int r = 0; ++ ++ tim397_page(); ++ ++ r += unittests_assert_16k_page( 0x0000, tim397_memory_source, 0 ); ++ r += unittests_assert_16k_ram_page( 0x4000, 5 ); ++ r += unittests_assert_16k_ram_page( 0x8000, 2 ); ++ r += unittests_assert_16k_ram_page( 0xc000, 0 ); ++ ++ tim397_unpage(); ++ ++ r += unittests_paging_test_48( 2 ); ++ ++ return r; ++} ++ ++ ++static void ++tim397_enabled_snapshot( libspectrum_snap *snap ) ++{ ++ return; ++} ++ ++static void ++tim397_from_snapshot( libspectrum_snap *snap ) ++{ ++ return; ++} ++ ++static void ++tim397_to_snapshot( libspectrum_snap *snap GCC_UNUSED ) ++{ ++ //if( !periph_is_active( PERIPH_TYPE_TIM397 ) ) return; ++ return; ++} ++ +diff -Naru fuse-1.1.1/peripherals/disk/ti_m397.h fuse-1.1.1.fdd3000/peripherals/disk/ti_m397.h +--- fuse-1.1.1/peripherals/disk/ti_m397.h 1970-01-01 01:00:00.000000000 +0100 ++++ fuse-1.1.1.fdd3000/peripherals/disk/ti_m397.h 2014-02-14 08:31:43.972546695 +0100 +@@ -0,0 +1,28 @@ ++/* ++ TIM397.h: Routines for handling the Timex TIM397 ++*/ ++ ++#ifndef FUSE_TIM397_H ++#define FUSE_TIM397_H ++ ++#include ++ ++#include ++ ++#include "fdd.h" ++ ++extern int tim397_available; /* Is the tim397 available for use? */ ++extern int tim397_active; /* tim397 enabled? */ ++ ++int tim397_init( void ); ++void tim397_end( void ); ++ ++void tim397_page( void ); ++void tim397_unpage( void ); ++ ++libspectrum_byte tim397_io_read( libspectrum_word port, int *attached ); ++void tim397_io_write( libspectrum_word port, libspectrum_byte b ); ++ ++int tim397_unittest( void ); ++ ++#endif /* #ifndef FUSE_tim397_H */ +diff -Naru fuse-1.1.1/periph.h fuse-1.1.1.fdd3000/periph.h +--- fuse-1.1.1/periph.h 2013-05-24 22:42:22.000000000 +0200 ++++ fuse-1.1.1.fdd3000/periph.h 2014-02-14 08:21:36.769616238 +0100 +@@ -65,6 +65,7 @@ + PERIPH_TYPE_SPECCYBOOT, /* SpeccyBoot interface */ + PERIPH_TYPE_SPECDRUM, /* SpecDrum interface */ + PERIPH_TYPE_SPECTRANET, /* Spectranet interface */ ++ PERIPH_TYPE_TIM397, /* FDD3000 disk interface */ + PERIPH_TYPE_ULA, /* Standard ULA */ + PERIPH_TYPE_ULA_FULL_DECODE,/* Standard ULA responding only to 0xfe */ + PERIPH_TYPE_UPD765, /* +3 uPD765 FDC */ +diff -Naru fuse-1.1.1/settings.dat fuse-1.1.1.fdd3000/settings.dat +--- fuse-1.1.1/settings.dat 2013-05-16 22:26:23.000000000 +0200 ++++ fuse-1.1.1.fdd3000/settings.dat 2014-02-14 08:27:14.978179040 +0100 +@@ -64,6 +64,7 @@ + interface2, boolean, 1 + snapsasz80, null, 0 + opus, boolean, 0 ++ti_m397, boolean, 0 + pal_tv2x, boolean, 0 + movie_compr, string, NULL + movie_start, string, NULL +@@ -235,6 +236,7 @@ + rom_plusd, string, "plusd.rom", + rom_disciple, string, "disciple.rom", + rom_opus, string, "opus.rom", ++rom_tim397, string, "ti_m397.rom", + rom_speccyboot, string, "speccyboot-1.4.rom", + + drive_plus3a_type, string, NULL +diff -Naru fuse-1.1.1/settings.pl fuse-1.1.1.fdd3000/settings.pl +--- fuse-1.1.1/settings.pl 2013-05-24 22:42:22.000000000 +0200 ++++ fuse-1.1.1.fdd3000/settings.pl 2014-02-14 08:25:30.881179995 +0100 +@@ -762,7 +762,8 @@ + case 42: return &( settings->rom_plusd ); + case 43: return &( settings->rom_disciple ); + case 44: return &( settings->rom_opus ); +- case 45: return &( settings->rom_speccyboot ); ++ case 45: return &( settings->rom_tim397 ); ++ case 46: return &( settings->rom_speccyboot ); + default: return NULL; + } + } +diff -Naru fuse-1.1.1/ui/options.dat fuse-1.1.1.fdd3000/ui/options.dat +--- fuse-1.1.1/ui/options.dat 2013-05-24 22:42:22.000000000 +0200 ++++ fuse-1.1.1.fdd3000/ui/options.dat 2014-02-14 08:21:36.769616238 +0100 +@@ -64,6 +64,7 @@ + Checkbox, (B)eta 128 interface, beta128, INPUT_KEY_b + Checkbox, Beta 128 (a)uto-boot in 48K machines, beta128_48boot, INPUT_KEY_a + Checkbox, (O)pus Discovery interface, opus, INPUT_KEY_o ++Checkbox, FDD(3)000 / M397 interface, ti_m397, INPUT_KEY_3 + Postcheck, periph_postcheck + Posthook, periph_posthook + +diff -Naru fuse-1.1.1/ui/ui.h fuse-1.1.1.fdd3000/ui/ui.h +--- fuse-1.1.1/ui/ui.h 2013-05-16 22:26:23.000000000 +0200 ++++ fuse-1.1.1.fdd3000/ui/ui.h 2014-02-14 08:21:36.769616238 +0100 +@@ -39,6 +39,7 @@ + #include "peripherals/disk/beta.h" + #include "peripherals/disk/disciple.h" + #include "peripherals/disk/opus.h" ++#include "peripherals/disk/ti_m397.h" + #include "peripherals/disk/plusd.h" + #include "ui/scaler/scaler.h" + +@@ -211,6 +212,7 @@ + UI_MENU_ITEM_MEDIA_DISK_OPUS_2_EJECT, + UI_MENU_ITEM_MEDIA_DISK_OPUS_2_FLIP_SET, + UI_MENU_ITEM_MEDIA_DISK_OPUS_2_WP_SET, ++ UI_MENU_ITEM_MEDIA_DISK_TIM397, + UI_MENU_ITEM_MEDIA_IDE, + UI_MENU_ITEM_MEDIA_IDE_SIMPLE8BIT, + UI_MENU_ITEM_MEDIA_IDE_SIMPLE8BIT_MASTER_EJECT, +diff -Naru fuse-1.1.1/ui.c fuse-1.1.1.fdd3000/ui.c +--- fuse-1.1.1/ui.c 2013-05-16 22:26:23.000000000 +0200 ++++ fuse-1.1.1.fdd3000/ui.c 2014-02-14 08:51:58.576646341 +0100 +@@ -548,6 +549,8 @@ + "/Media/Disk/Opus/Drive 2/Write protect/Enable", + "/Media/Disk/Opus/Drive 2/Write protect/Disable", 1 }, + ++ { UI_MENU_ITEM_MEDIA_DISK_TIM397, "/Media/Disk/Timex M397" }, ++ + { UI_MENU_ITEM_MEDIA_IDE, "/Media/IDE" }, + + { UI_MENU_ITEM_MEDIA_IDE_SIMPLE8BIT, "/Media/IDE/Simple 8-bit" }, +diff -Naru fuse-1.1.1/z80/coretest.c fuse-1.1.1.fdd3000/z80/coretest.c +--- fuse-1.1.1/z80/coretest.c 2013-05-16 22:26:16.000000000 +0200 ++++ fuse-1.1.1.fdd3000/z80/coretest.c 2014-02-14 08:21:36.769616238 +0100 +@@ -459,6 +459,21 @@ + abort(); + } + ++int tim397_available = 0; ++int tim397_active = 0; ++ ++void ++tim397_page( void ) ++{ ++ abort(); ++} ++ ++void ++tim397_unpage( void ) ++{ ++ abort(); ++} ++ + int plusd_available = 0; + int plusd_active = 0; + +diff -Naru fuse-1.1.1/z80/z80_checks.h fuse-1.1.1.fdd3000/z80/z80_checks.h +--- fuse-1.1.1/z80/z80_checks.h 2013-05-16 22:26:16.000000000 +0200 ++++ fuse-1.1.1.fdd3000/z80/z80_checks.h 2014-02-14 08:23:42.063410052 +0100 +@@ -2,6 +2,7 @@ + SETUP_CHECK( rzx, rzx_playback ) + SETUP_CHECK( debugger, debugger_mode != DEBUGGER_MODE_INACTIVE ) + SETUP_CHECK( beta, beta_available ) ++SETUP_CHECK( tim397, tim397_available ) + SETUP_CHECK( plusd, plusd_available ) + SETUP_CHECK( disciple, disciple_available ) + SETUP_CHECK( if1p, if1_available ) +diff -Naru fuse-1.1.1/z80/z80_ops.c fuse-1.1.1.fdd3000/z80/z80_ops.c +--- fuse-1.1.1/z80/z80_ops.c 2013-05-16 22:26:16.000000000 +0200 ++++ fuse-1.1.1.fdd3000/z80/z80_ops.c 2014-02-14 08:23:33.485342586 +0100 +@@ -36,6 +36,7 @@ + #include "peripherals/disk/disciple.h" + #include "peripherals/disk/opus.h" + #include "peripherals/disk/plusd.h" ++#include "peripherals/disk/ti_m397.h" + #include "peripherals/ide/divide.h" + #include "peripherals/if1.h" + #include "peripherals/spectranet.h" +@@ -176,6 +177,18 @@ + } + + END_CHECK ++ ++ CHECK( tim397, tim397_available ) ++ ++ if( tim397_active ) { ++ if( PC == 0x0604 ) { ++ tim397_unpage(); ++ } ++ } else if( PC == 0x0000 || PC == 0x0008 ) { ++ tim397_page(); ++ } ++ ++ END_CHECK + + CHECK( plusd, plusd_available ) + -- 2.43.0