1 diff -Naru fuse-1.1.1-vanilla/fuse.c fuse-1.1.1/fuse.c
2 --- fuse-1.1.1-vanilla/fuse.c 2013-05-16 22:26:23.000000000 +0200
3 +++ fuse-1.1.1/fuse.c 2014-02-21 12:46:19.947908386 +0100
12 diff -Naru fuse-1.1.1-vanilla/machines/machines_periph.c fuse-1.1.1/machines/machines_periph.c
13 --- fuse-1.1.1-vanilla/machines/machines_periph.c 2013-05-16 22:26:11.000000000 +0200
14 +++ fuse-1.1.1/machines/machines_periph.c 2014-02-21 12:46:19.947908386 +0100
16 periph_set_present( PERIPH_TYPE_FULLER, PERIPH_PRESENT_OPTIONAL );
17 periph_set_present( PERIPH_TYPE_ZXPRINTER, PERIPH_PRESENT_OPTIONAL );
18 periph_set_present( PERIPH_TYPE_DISCIPLE, PERIPH_PRESENT_OPTIONAL );
19 + periph_set_present( PERIPH_TYPE_TIM397, PERIPH_PRESENT_OPTIONAL );
22 /* The set of peripherals available on the 128K and similar machines */
23 diff -Naru fuse-1.1.1-vanilla/Makefile.in fuse-1.1.1/Makefile.in
24 --- fuse-1.1.1-vanilla/Makefile.in 2013-05-30 00:21:33.000000000 +0200
25 +++ fuse-1.1.1/Makefile.in 2014-02-21 12:46:19.947908386 +0100
27 LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
29 LIBPNG_CONFIG = @LIBPNG_CONFIG@
32 LIBSPEC_CFLAGS = @LIBSPEC_CFLAGS@
33 LIBSPEC_HAVE_AUDIOFILE = @LIBSPEC_HAVE_AUDIOFILE@
34 LIBSPEC_HAVE_BZ2 = @LIBSPEC_HAVE_BZ2@
35 diff -Naru fuse-1.1.1-vanilla/memory.c fuse-1.1.1/memory.c
36 --- fuse-1.1.1-vanilla/memory.c 2013-05-16 22:26:23.000000000 +0200
37 +++ fuse-1.1.1/memory.c 2014-02-21 12:46:19.947908386 +0100
41 #include "peripherals/disk/opus.h"
42 +#include "peripherals/disk/ti_m397.h"
43 #include "peripherals/spectranet.h"
44 #include "peripherals/ula.h"
46 diff -Naru fuse-1.1.1-vanilla/menu.c fuse-1.1.1/menu.c
47 --- fuse-1.1.1-vanilla/menu.c 2013-05-16 22:26:23.000000000 +0200
48 +++ fuse-1.1.1/menu.c 2014-02-21 12:46:19.947908386 +0100
50 #include "peripherals/disk/beta.h"
51 #include "peripherals/disk/disciple.h"
52 #include "peripherals/disk/opus.h"
53 +#include "peripherals/disk/ti_m397.h"
54 #include "peripherals/disk/plusd.h"
55 #include "peripherals/ide/divide.h"
56 #include "peripherals/ide/simpleide.h"
58 case 18: menu_select_roms_with_title( "+D", 42, 1 ); return;
59 case 19: menu_select_roms_with_title( "DISCiPLE", 43, 1 ); return;
60 case 20: menu_select_roms_with_title( "Opus Discovery", 44, 1 ); return;
61 - case 21: menu_select_roms_with_title( "SpeccyBoot", 45, 1 ); return;
62 + case 21: menu_select_roms_with_title( "Timex M397", 45, 1 ); return;
63 + case 22: menu_select_roms_with_title( "SpeccyBoot", 46, 1 ); return;
67 diff -Naru fuse-1.1.1-vanilla/menu_data.dat fuse-1.1.1/menu_data.dat
68 --- fuse-1.1.1-vanilla/menu_data.dat 2013-05-16 22:26:23.000000000 +0200
69 +++ fuse-1.1.1/menu_data.dat 2014-02-21 12:46:19.947908386 +0100
71 Options/Select ROMs/+_D..., Item,, menu_options_selectroms_select,, 18
72 Options/Select ROMs/DISCiP_LE..., Item,, menu_options_selectroms_select,, 19
73 Options/Select ROMs/_Opus Discovery..., Item,, menu_options_selectroms_select,, 20
74 -Options/Select ROMs/Specc_yBoot..., Item,, menu_options_selectroms_select,, 21
75 +Options/Select ROMs/_Timex M397..., Item,, menu_options_selectroms_select,, 21
76 +Options/Select ROMs/Specc_yBoot..., Item,, menu_options_selectroms_select,, 22
78 Options/_Filter..., Item,,, menu_filter_detail
80 diff -Naru fuse-1.1.1-vanilla/peripherals/disk/Makefile.am fuse-1.1.1/peripherals/disk/Makefile.am
81 --- fuse-1.1.1-vanilla/peripherals/disk/Makefile.am 2013-05-16 22:26:03.000000000 +0200
82 +++ fuse-1.1.1/peripherals/disk/Makefile.am 2014-02-21 11:33:59.000000000 +0100
91 noinst_HEADERS = beta.h \
99 diff -Naru fuse-1.1.1-vanilla/peripherals/disk/Makefile.in fuse-1.1.1/peripherals/disk/Makefile.in
100 --- fuse-1.1.1-vanilla/peripherals/disk/Makefile.in 2013-05-24 22:56:08.000000000 +0200
101 +++ fuse-1.1.1/peripherals/disk/Makefile.in 2014-02-21 11:36:56.000000000 +0100
104 am_libdisk_a_OBJECTS = beta.$(OBJEXT) crc.$(OBJEXT) disciple.$(OBJEXT) \
105 disk.$(OBJEXT) fdd.$(OBJEXT) opus.$(OBJEXT) plusd.$(OBJEXT) \
106 - upd_fdc.$(OBJEXT) wd_fdc.$(OBJEXT)
107 + upd_fdc.$(OBJEXT) ti_m397.$(OBJEXT) ti_m397ipc.$(OBJEXT) wd_fdc.$(OBJEXT)
108 libdisk_a_OBJECTS = $(am_libdisk_a_OBJECTS)
109 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
110 depcomp = $(SHELL) $(top_srcdir)/depcomp
119 noinst_HEADERS = beta.h \
130 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opus.Po@am__quote@
131 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plusd.Po@am__quote@
132 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upd_fdc.Po@am__quote@
133 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ti_m397.Po@am__quote@
134 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ti_m397ipc.Po@am__quote@
135 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wd_fdc.Po@am__quote@
138 diff -Naru fuse-1.1.1-vanilla/peripherals/disk/ti_m397.c fuse-1.1.1/peripherals/disk/ti_m397.c
139 --- fuse-1.1.1-vanilla/peripherals/disk/ti_m397.c 1970-01-01 01:00:00.000000000 +0100
140 +++ fuse-1.1.1/peripherals/disk/ti_m397.c 2014-02-21 12:53:49.314520701 +0100
142 +/******************************************************************************
143 + This file is a part od FDD3000 Emulator
145 + Copyright (C) 2013,2014 by SÅ‚awomir Szczyrba <sszczyrba@gmail.com>
146 + Copyright (C) 2014 by Stefano Bodrato <stefano_bodrato hotmail dt com>
148 + This program is free software: you can redistribute it and/or modify it under
149 + the terms of the GNU Lesser General Public License as published by the Free
150 + Software Foundation, either version 2 of the License, or (at your option) any
153 + This program is distributed in the hope that it will be useful, but WITHOUT
154 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
155 + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
158 + You should have received a copy of the GNU Lesser General Public License
159 + along with this program. If not, see <http://www.gnu.org/licenses/lgpl.html>
160 +******************************************************************************/
166 + #define MSG(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
172 +#include <libspectrum.h>
173 +#include "settings.h"
176 +#include "unittests/unittests.h"
178 +#include "ti_m397.h"
179 +#include "ti_m397ipc.h"
181 +/*************************************************************************/
183 +libspectrum_byte tim397_io_read( libspectrum_word port, int *attached ) {
184 + libspectrum_byte b = 0;
185 + if(ipc&&connected) {
186 +//MSG("Reading from port: %u,",port&0xff);
187 + if(fddIsAlive()) { b=fddRead(); } else { connected=0; /*semResetAll();*/ return 0; }
190 +//MSG("%u\n",b&0xff);
194 +void tim397_io_write( libspectrum_word port, libspectrum_byte b ) {
195 + if(ipc&&connected) {
196 +//MSG("Writing %u to port: %u\n",b&0xff,port&0xff);
197 + if(fddIsAlive()) { fddWrite(b); } else { connected=0; /*semResetAll();*/ }
201 +/*************************************************************************/
203 +static void tim397_reset( int hard_reset );
204 +static void tim397_memory_map( void );
205 +static void tim397_enabled_snapshot( libspectrum_snap *snap );
206 +static void tim397_from_snapshot( libspectrum_snap *snap );
207 +static void tim397_to_snapshot( libspectrum_snap *snap );
208 +static void tim397_activate( void );
211 +/* Two 8Kb memory chunks accessible by the Z80 when /ROMCS is low */
212 +static memory_page tim397_memory_map_romcs_rom[ MEMORY_PAGES_IN_8K ];
213 +static memory_page tim397_memory_map_romcs_ram[ MEMORY_PAGES_IN_8K ];
214 +static int tim397_memory_source;
216 +int tim397_available = 0;
217 +int tim397_active = 0;
219 +static libspectrum_byte *tim397_ram;
220 +static int memory_allocated = 0;
222 +static module_info_t tim397_module_info = {
225 + tim397_enabled_snapshot,
226 + tim397_from_snapshot,
234 + machine_current->ram.romcs = 1;
235 + machine_current->memory_map();
236 + ui_statusbar_update( UI_STATUSBAR_ITEM_DISK, UI_STATUSBAR_STATE_ACTIVE );
237 + MSG("tim397_page\n");
241 +tim397_unpage( void )
244 + machine_current->ram.romcs = 0;
245 + machine_current->memory_map();
246 + ui_statusbar_update( UI_STATUSBAR_ITEM_DISK, UI_STATUSBAR_STATE_INACTIVE );
247 + MSG("tim397_unpage\n");
251 +tim397_memory_map( void )
253 + if( !tim397_active ) return;
254 + memory_map_romcs_8k( 0x0000, tim397_memory_map_romcs_rom );
255 + memory_map_romcs_8k( 0x2000, tim397_memory_map_romcs_ram );
256 + MSG("tim397_memory_map\n");
259 +static const periph_port_t tim397_ports[] = {
260 + { 0x00ff, 0x00ef, tim397_io_read, tim397_io_write },
261 + { 0, 0, NULL, NULL }
264 +static const periph_t tim397_periph = {
265 + &settings_current.ti_m397,
275 + module_register( &tim397_module_info );
277 + tim397_memory_source = memory_source_register( "TI_M397" );
278 + for( i = 0; i < MEMORY_PAGES_IN_8K; i++ )
279 + tim397_memory_map_romcs_rom[ i ].source = tim397_memory_source;
280 + for( i = 0; i < MEMORY_PAGES_IN_8K; i++ )
281 + tim397_memory_map_romcs_ram[ i ].source = tim397_memory_source;
282 + periph_register( PERIPH_TYPE_TIM397, &tim397_periph );
286 + MSG("tim397_init\n");
293 +tim397_reset( int hard_reset )
298 + tim397_available = 0;
300 + if( !periph_is_active( PERIPH_TYPE_TIM397 ) ) {
301 + ui_statusbar_update( UI_STATUSBAR_ITEM_DISK,
302 + UI_STATUSBAR_STATE_NOT_AVAILABLE );
303 + MSG("FDD3000 is inactive\n");
307 + if (openShm()!=0) {
308 +// settings_current.ti_m397 = 0;
309 +// periph_activate_type( PERIPH_TYPE_TIM397, 0 );
310 + MSG("Link to FDD3000 emulator failed\n");
314 + if( machine_load_rom_bank( tim397_memory_map_romcs_rom, 0,
315 + settings_current.rom_tim397,
316 + settings_default.rom_tim397, 0x1000 ) ||
317 + machine_load_rom_bank( tim397_memory_map_romcs_rom, 0x1000,
318 + settings_current.rom_tim397,
319 + settings_default.rom_tim397, 0x1000 ) ) {
320 + settings_current.ti_m397 = 0;
321 + periph_activate_type( PERIPH_TYPE_TIM397, 0 );
322 + ui_statusbar_update( UI_STATUSBAR_ITEM_DISK,
323 + UI_STATUSBAR_STATE_NOT_AVAILABLE );
324 + MSG("Cannot load ROM file (%s, nor %s)\n",settings_current.rom_tim397,settings_default.rom_tim397);
328 + machine_current->ram.romcs = 0;
330 + for( i = 0; i < MEMORY_PAGES_IN_8K; i++ ) {
331 + tim397_memory_map_romcs_ram[ i ].page = &tim397_ram[ i * MEMORY_PAGE_SIZE ];
332 + tim397_memory_map_romcs_ram[ i ].writable = 1;
335 + tim397_available = 1;
339 + memset( tim397_ram, 0, 0x2000 );
342 + machine_current->memory_map();
344 + ui_statusbar_update( UI_STATUSBAR_ITEM_DISK, UI_STATUSBAR_STATE_INACTIVE );
345 + MSG("tim397_reset\n");
351 + tim397_available = 0;
352 + closeShm(); // ? //
354 + MSG("tim397_end\n");
358 +tim397_activate( void )
360 + if( !memory_allocated ) {
361 + tim397_ram = memory_pool_allocate_persistent( 0x2000, 1 );
362 + memory_allocated = 1;
364 + MSG("tim397_activate\n");
368 +tim397_unittest( void )
374 + r += unittests_assert_16k_page( 0x0000, tim397_memory_source, 0 );
375 + r += unittests_assert_16k_ram_page( 0x4000, 5 );
376 + r += unittests_assert_16k_ram_page( 0x8000, 2 );
377 + r += unittests_assert_16k_ram_page( 0xc000, 0 );
381 + r += unittests_paging_test_48( 2 );
388 +tim397_enabled_snapshot( libspectrum_snap *snap )
394 +tim397_from_snapshot( libspectrum_snap *snap )
400 +tim397_to_snapshot( libspectrum_snap *snap GCC_UNUSED )
405 diff -Naru fuse-1.1.1-vanilla/peripherals/disk/ti_m397.h fuse-1.1.1/peripherals/disk/ti_m397.h
406 --- fuse-1.1.1-vanilla/peripherals/disk/ti_m397.h 1970-01-01 01:00:00.000000000 +0100
407 +++ fuse-1.1.1/peripherals/disk/ti_m397.h 2014-02-21 08:40:00.000000000 +0100
410 + TIM397.h: Routines for handling the Timex TIM397
413 +#ifndef FUSE_TIM397_H
414 +#define FUSE_TIM397_H
416 +#include <libspectrum.h>
418 +extern int tim397_available; /* Is the tim397 available for use? */
419 +extern int tim397_active; /* tim397 enabled? */
421 +int tim397_init( void );
422 +void tim397_end( void );
424 +void tim397_page( void );
425 +void tim397_unpage( void );
427 +libspectrum_byte tim397_io_read( libspectrum_word port, int *attached );
428 +void tim397_io_write( libspectrum_word port, libspectrum_byte b );
430 +int tim397_unittest( void );
432 +#endif /* #ifndef FUSE_tim397_H */
433 diff -Naru fuse-1.1.1-vanilla/peripherals/disk/ti_m397ipc.c fuse-1.1.1/peripherals/disk/ti_m397ipc.c
434 --- fuse-1.1.1-vanilla/peripherals/disk/ti_m397ipc.c 1970-01-01 01:00:00.000000000 +0100
435 +++ fuse-1.1.1/peripherals/disk/ti_m397ipc.c 2014-02-21 12:54:02.208140764 +0100
437 +/******************************************************************************
438 + This file is a part od FDD3000 Emulator
440 + Copyright (C) 2013,2014 by SÅ‚awomir Szczyrba <sszczyrba@gmail.com>
441 + Copyright (C) 2014 by Stefano Bodrato <stefano_bodrato hotmail dt com>
443 + This program is free software: you can redistribute it and/or modify it under
444 + the terms of the GNU Lesser General Public License as published by the Free
445 + Software Foundation, either version 2 of the License, or (at your option) any
448 + This program is distributed in the hope that it will be useful, but WITHOUT
449 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
450 + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
453 + You should have received a copy of the GNU Lesser General Public License
454 + along with this program. If not, see <http://www.gnu.org/licenses/lgpl.html>
455 +******************************************************************************/
461 + #define MSG(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
468 +#include <libspectrum.h>
474 +#include <sys/stat.h> /* For mode constants */
475 +#include <sys/types.h>
479 +#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__)
481 +#include <windows.h>
486 +#include <semaphore.h>
488 +#define SEM_FAILED -1
490 +#include <sys/mman.h>
491 +#include <sys/ipc.h>
492 +#include <sys/msg.h>
493 +#include <sys/socket.h>
501 +typedef struct tFdd2TiLink {
508 +fdd2TiLink * fddlink;
515 +#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__)
517 +HANDLE fdd2tiF, fdd2tiE, ti2fddF, ti2fddE, fddAlive;
521 +TCHAR *shmId = _T("\\fdd.data");
522 +TCHAR szTempFileName[MAX_PATH];
523 +TCHAR lpTempPathBuffer[MAX_PATH];
526 +TCHAR fdd2tiE_Id[]=TEXT("Global\\fdd.fdd2ti.empty");
527 +TCHAR fdd2tiF_Id[]=TEXT("Global\\fdd.fdd2ti.full");
528 +TCHAR ti2fddE_Id[]=TEXT("Global\\fdd.ti2fdd.empty");
529 +TCHAR ti2fddF_Id[]=TEXT("Global\\fdd.ti2fdd.full");
530 +TCHAR fddAlive_Id[]=TEXT("Global\\fdd.alive");
535 +sem_t *fdd2tiF,*fdd2tiE,*ti2fddF,*ti2fddE,*fddAlive;
536 +const char * shmId = "fdd.data";
537 +const char * fddAlive_Id = "fdd.alive";
538 +const char * fdd2tiE_Id = "fdd.fdd2ti.empty";
539 +const char * fdd2tiF_Id = "fdd.fdd2ti.full";
540 +const char * ti2fddE_Id = "fdd.ti2fdd.empty";
541 +const char * ti2fddF_Id = "fdd.ti2fdd.full";
547 +#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__)
548 + if (WaitForSingleObject(fdd2tiF,INFINITE) == 0 ) {
549 + data=fddlink->fdd2ti;
550 + ReleaseSemaphore(fdd2tiE,1,NULL);
551 + } else { connected = 0; }
554 + data=fddlink->fdd2ti;
560 +void fddWrite(int8_t d) {
561 +#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__)
562 + if(WaitForSingleObject(ti2fddE,INFINITE) == 0 ) {
564 + ReleaseSemaphore(ti2fddF,1,NULL);
565 + } else { connected = 0; }
573 +uint8_t fddIsAlive() {
575 +#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__)
576 + WaitForSingleObject(fddAlive,INFINITE);
577 + ok=fddlink->fddAlive&fddlink->tiAlive;
578 + ReleaseSemaphore(fddAlive,1,NULL);
580 + sem_wait(fddAlive);
581 + ok=fddlink->fddAlive&fddlink->tiAlive;
582 + sem_post(fddAlive);
591 + if(!ipc) { return; }
594 +#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__)
596 + WaitForSingleObject(fddAlive,INFINITE);
597 + fddlink->tiAlive=0;
598 + i=fddlink->fddAlive;
599 + ReleaseSemaphore(fddAlive,1,NULL);
602 + CloseHandle(fddAlive);
603 + CloseHandle(ti2fddF);
604 + CloseHandle(ti2fddE);
605 + CloseHandle(fdd2tiF);
606 + CloseHandle(fdd2tiE);
608 + UnmapViewOfFile(fddlink);
616 + sem_wait(fddAlive);
617 + fddlink->tiAlive=0;
618 + i=fddlink->fddAlive;
619 + sem_post(fddAlive);
621 + sem_close(fddAlive);
622 + sem_close(ti2fddF);
623 + sem_close(ti2fddE);
624 + sem_close(fdd2tiF);
625 + sem_close(fdd2tiE);
627 + munmap(fddlink,sizeof(fdd2TiLink));
629 + sem_unlink(fdd2tiE_Id);
630 + sem_unlink(fdd2tiF_Id);
631 + sem_unlink(ti2fddE_Id);
632 + sem_unlink(ti2fddF_Id);
633 + sem_unlink(fddAlive_Id);
646 +#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__)
649 +// tmp=getenv("TMP");
650 +// if(tmp==NULL) tmp=getenv("TEMP");
651 +// if(tmp==NULL) tmp=".";
653 +// strcpy(shmId,tmp);
654 +// strcat(shmId,"\\fdd.data");
655 + dwRetVal = GetTempPath(MAX_PATH, lpTempPathBuffer); // buffer for path
656 + if (dwRetVal > MAX_PATH || (dwRetVal == 0)) {
657 + MSG("tim397_openShm: GetTempPath failed\n");
660 + snprintf(szTempFileName,MAX_PATH,"%s%s",lpTempPathBuffer,shmId);
662 + MSG("TMP Shm file : %s\n",szTempFileName);
666 + GENERIC_READ|GENERIC_WRITE,
667 + FILE_SHARE_READ|FILE_SHARE_WRITE,
670 + FILE_ATTRIBUTE_NORMAL,
674 + if (shmf == NULL) {
675 + MSG("failed to open file %s. ErrorCode: %d\n",shmId,GetLastError());
679 + shm = CreateFileMapping(
680 + shmf, // use paging file
681 + NULL, // default security
682 + PAGE_READWRITE, // read/write access
683 + 0, // maximum object size (high-order DWORD)
684 + 256, // maximum object size (low-order DWORD)
689 + MSG("failed to map file. ErrorCode: %d\n",GetLastError());
693 + //fddlink=(fdd2TiLink*)mmap(0,sizeof(fdd2TiLink),PROT_READ|PROT_WRITE,MAP_SHARED,shm,0);
694 + fddlink = (fdd2TiLink*)MapViewOfFile(shm, // handle to map object
695 + FILE_MAP_ALL_ACCESS, // read/write permission
702 + MSG("tim397_openShm: MapViewOfFile (mmap) failed\n");
708 + fdd2tiE=OpenSemaphore(SEMAPHORE_MODIFY_STATE|SYNCHRONIZE,TRUE,fdd2tiE_Id);
709 + if(fdd2tiE==NULL){MSG("failed to create sem fdd2tie. ErrorCode: %d\n",GetLastError()); }
711 + fdd2tiF=OpenSemaphore(SEMAPHORE_MODIFY_STATE|SYNCHRONIZE,TRUE,fdd2tiF_Id);
712 + if(fdd2tiF==NULL){MSG("failed to create sem fdd2tif. ErrorCode: %d\n",GetLastError()); }
714 + ti2fddE=OpenSemaphore(SEMAPHORE_MODIFY_STATE|SYNCHRONIZE,TRUE,ti2fddE_Id);
715 + if(ti2fddE==NULL){MSG("failed to create sem ti2fdde. ErrorCode: %d\n",GetLastError()); }
717 + ti2fddF=OpenSemaphore(SEMAPHORE_MODIFY_STATE|SYNCHRONIZE,TRUE,ti2fddF_Id);
718 + if(ti2fddF==NULL){MSG("failed to create sem ti2fddf. ErrorCode: %d\n",GetLastError()); }
720 + fddAlive=OpenSemaphore(SEMAPHORE_MODIFY_STATE|SYNCHRONIZE,TRUE,fddAlive_Id);
721 + if(fddAlive==NULL){MSG("failed to create sem sync. ErrorCode: %d\n",GetLastError()); }
723 + if ((fdd2tiE==NULL) || (fdd2tiF==NULL) || (ti2fddE==NULL) || (ti2fddF==NULL) || (fddAlive==NULL)) {
724 + MSG("tim397_openShm: semaphore creation failed\n");
730 + shm = shm_open(shmId, O_RDWR, 0666);
732 + MSG("tim397_openShm: shm_open file %s failed\n",shmId);
735 + trunc=ftruncate(shm,sizeof(fdd2TiLink));
737 + MSG("tim397_openShm: ftruncate failed\n");
740 + fddlink=(fdd2TiLink*)mmap(0,sizeof(fdd2TiLink),PROT_READ|PROT_WRITE,MAP_SHARED,shm,0);
741 + if(fddlink==MAP_FAILED) {
742 + MSG("tim397_openShm: mmap failed\n");
747 + fdd2tiE=sem_open(fdd2tiE_Id,O_RDWR,0666,1);
748 + if( SEM_FAILED == fdd2tiE) { MSG("fdd2tiE open failed\n"); }
750 + fdd2tiF=sem_open(fdd2tiF_Id,O_RDWR,0666,0);
751 + if( SEM_FAILED == fdd2tiF) { MSG("fdd2tiF open failed\n"); }
753 + ti2fddE=sem_open(ti2fddE_Id,O_RDWR,0666,1);
754 + if( SEM_FAILED == ti2fddE) { MSG("ti2fddE open failed\n"); }
756 + ti2fddF=sem_open(ti2fddF_Id,O_RDWR,0666,0);
757 + if( SEM_FAILED == ti2fddF) { MSG("ti2fddF open failed\n"); }
759 + fddAlive=sem_open(fddAlive_Id,O_RDWR,0666,1);
760 + if( SEM_FAILED == fddAlive){ MSG("fddAlive open failed\n"); }
762 + if ((fdd2tiE==SEM_FAILED) || (fdd2tiF==SEM_FAILED) || (ti2fddE==SEM_FAILED) || (ti2fddF==SEM_FAILED) || (fddAlive==SEM_FAILED)) {
763 + MSG("tim397_openShm: semaphore creation failed\n");
769 + if(ipc&&(!connected)) {
770 +#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__)
771 + WaitForSingleObject(fddAlive,INFINITE);
772 + if(fddlink->fddAlive){ fddlink->tiAlive=1; connected=1; }
773 + ReleaseSemaphore(fddAlive,1,NULL);
775 + sem_wait(fddAlive);
776 + if(fddlink->fddAlive){ fddlink->tiAlive=1; connected=1; }
777 + sem_post(fddAlive);
784 +void closeShm(void) {
785 + if(ipc&&connected) {
786 +#if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__)
787 + WaitForSingleObject(fddAlive,INFINITE);
788 + fddlink->tiAlive=0;
789 + ReleaseSemaphore(fddAlive,1,NULL);
791 + sem_wait(fddAlive);
792 + fddlink->tiAlive=0;
793 + sem_post(fddAlive);
797 diff -Naru fuse-1.1.1-vanilla/peripherals/disk/ti_m397ipc.h fuse-1.1.1/peripherals/disk/ti_m397ipc.h
798 --- fuse-1.1.1-vanilla/peripherals/disk/ti_m397ipc.h 1970-01-01 01:00:00.000000000 +0100
799 +++ fuse-1.1.1/peripherals/disk/ti_m397ipc.h 2014-02-21 09:59:00.000000000 +0100
802 + TIM397.h: Routines for handling the Timex TIM397
805 +#ifndef FUSE_TIM397IPC_H
806 +#define FUSE_TIM397IPC_H
811 +extern int connected;
814 +void closeShm(void);
817 +int fddIsAlive(void);
818 +uint8_t fddRead(void);
819 +void fddWrite(uint8_t);
821 +#endif /* #ifndef FUSE_tim397ipc_H */
822 diff -Naru fuse-1.1.1-vanilla/periph.h fuse-1.1.1/periph.h
823 --- fuse-1.1.1-vanilla/periph.h 2013-05-24 22:42:22.000000000 +0200
824 +++ fuse-1.1.1/periph.h 2014-02-21 12:46:19.951241793 +0100
826 PERIPH_TYPE_SPECCYBOOT, /* SpeccyBoot interface */
827 PERIPH_TYPE_SPECDRUM, /* SpecDrum interface */
828 PERIPH_TYPE_SPECTRANET, /* Spectranet interface */
829 + PERIPH_TYPE_TIM397, /* FDD3000 disk interface */
830 PERIPH_TYPE_ULA, /* Standard ULA */
831 PERIPH_TYPE_ULA_FULL_DECODE,/* Standard ULA responding only to 0xfe */
832 PERIPH_TYPE_UPD765, /* +3 uPD765 FDC */
833 diff -Naru fuse-1.1.1-vanilla/settings.dat fuse-1.1.1/settings.dat
834 --- fuse-1.1.1-vanilla/settings.dat 2013-05-16 22:26:23.000000000 +0200
835 +++ fuse-1.1.1/settings.dat 2014-02-21 12:46:19.951241793 +0100
837 interface2, boolean, 1
842 movie_compr, string, NULL
843 movie_start, string, NULL
845 rom_plusd, string, "plusd.rom",
846 rom_disciple, string, "disciple.rom",
847 rom_opus, string, "opus.rom",
848 +rom_tim397, string, "ti_m397.rom",
849 rom_speccyboot, string, "speccyboot-1.4.rom",
851 drive_plus3a_type, string, NULL
852 diff -Naru fuse-1.1.1-vanilla/settings.pl fuse-1.1.1/settings.pl
853 --- fuse-1.1.1-vanilla/settings.pl 2013-05-24 22:42:22.000000000 +0200
854 +++ fuse-1.1.1/settings.pl 2014-02-21 12:46:19.951241793 +0100
856 case 42: return &( settings->rom_plusd );
857 case 43: return &( settings->rom_disciple );
858 case 44: return &( settings->rom_opus );
859 - case 45: return &( settings->rom_speccyboot );
860 + case 45: return &( settings->rom_tim397 );
861 + case 46: return &( settings->rom_speccyboot );
862 default: return NULL;
865 diff -Naru fuse-1.1.1-vanilla/ui/options.dat fuse-1.1.1/ui/options.dat
866 --- fuse-1.1.1-vanilla/ui/options.dat 2013-05-24 22:42:22.000000000 +0200
867 +++ fuse-1.1.1/ui/options.dat 2014-02-21 12:46:19.951241793 +0100
869 Checkbox, (B)eta 128 interface, beta128, INPUT_KEY_b
870 Checkbox, Beta 128 (a)uto-boot in 48K machines, beta128_48boot, INPUT_KEY_a
871 Checkbox, (O)pus Discovery interface, opus, INPUT_KEY_o
872 +Checkbox, FDD(3)000 / M397 interface, ti_m397, INPUT_KEY_3
873 Postcheck, periph_postcheck
874 Posthook, periph_posthook
876 diff -Naru fuse-1.1.1-vanilla/ui/ui.h fuse-1.1.1/ui/ui.h
877 --- fuse-1.1.1-vanilla/ui/ui.h 2013-05-16 22:26:23.000000000 +0200
878 +++ fuse-1.1.1/ui/ui.h 2014-02-21 12:46:19.951241793 +0100
880 #include "peripherals/disk/beta.h"
881 #include "peripherals/disk/disciple.h"
882 #include "peripherals/disk/opus.h"
883 +#include "peripherals/disk/ti_m397.h"
884 #include "peripherals/disk/plusd.h"
885 #include "ui/scaler/scaler.h"
888 UI_MENU_ITEM_MEDIA_DISK_OPUS_2_EJECT,
889 UI_MENU_ITEM_MEDIA_DISK_OPUS_2_FLIP_SET,
890 UI_MENU_ITEM_MEDIA_DISK_OPUS_2_WP_SET,
891 + UI_MENU_ITEM_MEDIA_DISK_TIM397,
892 UI_MENU_ITEM_MEDIA_IDE,
893 UI_MENU_ITEM_MEDIA_IDE_SIMPLE8BIT,
894 UI_MENU_ITEM_MEDIA_IDE_SIMPLE8BIT_MASTER_EJECT,
895 diff -Naru fuse-1.1.1-vanilla/ui.c fuse-1.1.1/ui.c
896 --- fuse-1.1.1-vanilla/ui.c 2013-05-16 22:26:23.000000000 +0200
897 +++ fuse-1.1.1/ui.c 2014-02-21 12:46:19.951241793 +0100
899 "/Media/Disk/Opus/Drive 2/Write protect/Enable",
900 "/Media/Disk/Opus/Drive 2/Write protect/Disable", 1 },
902 + { UI_MENU_ITEM_MEDIA_DISK_TIM397, "/Media/Disk/Timex M397" },
904 { UI_MENU_ITEM_MEDIA_IDE, "/Media/IDE" },
906 { UI_MENU_ITEM_MEDIA_IDE_SIMPLE8BIT, "/Media/IDE/Simple 8-bit" },
907 diff -Naru fuse-1.1.1-vanilla/z80/coretest.c fuse-1.1.1/z80/coretest.c
908 --- fuse-1.1.1-vanilla/z80/coretest.c 2013-05-16 22:26:16.000000000 +0200
909 +++ fuse-1.1.1/z80/coretest.c 2014-02-21 12:46:19.951241793 +0100
914 +int tim397_available = 0;
915 +int tim397_active = 0;
924 +tim397_unpage( void )
929 int plusd_available = 0;
930 int plusd_active = 0;
932 diff -Naru fuse-1.1.1-vanilla/z80/z80_checks.h fuse-1.1.1/z80/z80_checks.h
933 --- fuse-1.1.1-vanilla/z80/z80_checks.h 2013-05-16 22:26:16.000000000 +0200
934 +++ fuse-1.1.1/z80/z80_checks.h 2014-02-21 12:46:19.951241793 +0100
936 SETUP_CHECK( rzx, rzx_playback )
937 SETUP_CHECK( debugger, debugger_mode != DEBUGGER_MODE_INACTIVE )
938 SETUP_CHECK( beta, beta_available )
939 +SETUP_CHECK( tim397, tim397_available )
940 SETUP_CHECK( plusd, plusd_available )
941 SETUP_CHECK( disciple, disciple_available )
942 SETUP_CHECK( if1p, if1_available )
943 diff -Naru fuse-1.1.1-vanilla/z80/z80_ops.c fuse-1.1.1/z80/z80_ops.c
944 --- fuse-1.1.1-vanilla/z80/z80_ops.c 2013-05-16 22:26:16.000000000 +0200
945 +++ fuse-1.1.1/z80/z80_ops.c 2014-02-21 12:46:19.951241793 +0100
947 #include "peripherals/disk/disciple.h"
948 #include "peripherals/disk/opus.h"
949 #include "peripherals/disk/plusd.h"
950 +#include "peripherals/disk/ti_m397.h"
951 #include "peripherals/ide/divide.h"
952 #include "peripherals/if1.h"
953 #include "peripherals/spectranet.h"
959 + CHECK( tim397, tim397_available )
961 + if( tim397_active ) {
962 + if( PC == 0x0604 ) {
965 + } else if( PC == 0x0000 || PC == 0x0008 ) {
971 CHECK( plusd, plusd_available )