static void didaktik_from_snapshot( libspectrum_snap *snap ) { int i; if( !libspectrum_snap_didaktik80_active( snap ) ) return; if( libspectrum_snap_didaktik80_custom_rom( snap ) && libspectrum_snap_didaktik80_rom( snap, 0 ) && machine_load_rom_bank_from_buffer( didaktik_memory_map_romcs_rom, 0, libspectrum_snap_didaktik80_rom( snap, 0 ), ROM_SIZE, 1 ) ) return; if( libspectrum_snap_didaktik80_ram( snap, 0 ) ) { for( i = 0; i < MEMORY_PAGES_IN_2K; i++ ) memcpy( didaktik_memory_map_romcs_ram[ i ].page, libspectrum_snap_didaktik80_ram( snap, 0 ) + i * MEMORY_PAGE_SIZE, MEMORY_PAGE_SIZE ); } /* ignore drive count for now, there will be an issue with loading snaps where drives have been disabled libspectrum_snap_didaktik80_drive_count( snap ) */ didaktik_fdc->direction = libspectrum_snap_plusd_direction( snap ); didaktik_cr_write ( 0x0081, libspectrum_snap_didaktik80_status ( snap ) ); didaktik_tr_write ( 0x0083, libspectrum_snap_didaktik80_track ( snap ) ); didaktik_sec_write( 0x0085, libspectrum_snap_didaktik80_sector ( snap ) ); didaktik_dr_write ( 0x0087, libspectrum_snap_didaktik80_data ( snap ) ); didaktik_aux_write( 0x0089, libspectrum_snap_didaktik80_aux ( snap ) ); if( libspectrum_snap_didaktik80_paged( snap ) ) { didaktik80_page(); } else { didaktik80_unpage(); } }
int didaktik80_unittest( void ) { int r = 0; didaktik80_page(); r += unittests_assert_8k_page( 0x0000, didaktik_rom_memory_source, 0 ); r += unittests_assert_4k_page( 0x2000, didaktik_rom_memory_source, 0 ); r += unittests_assert_2k_page( 0x3000, didaktik_rom_memory_source, 0 ); r += unittests_assert_2k_page( 0x3800, didaktik_ram_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 ); didaktik80_unpage(); r += unittests_paging_test_48( 2 ); return r; }
/* Execute Z80 opcodes until the next event */ void z80_do_opcodes( void ) { #ifdef HAVE_ENOUGH_MEMORY libspectrum_byte opcode = 0x00; #endif int even_m1 = machine_current->capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_EVEN_M1; #ifdef __GNUC__ #undef SETUP_CHECK #define SETUP_CHECK( label, condition ) \ if( condition ) { cgoto[ next ] = &&label; next = pos_##label + 1; } \ check++; #undef SETUP_NEXT #define SETUP_NEXT( label ) \ if( next != check ) { cgoto[ next ] = &&label; } \ next = check; void *cgoto[ numchecks ]; size_t next = 0; size_t check = 0; #include "z80_checks.h" #endif /* #ifdef __GNUC__ */ while( tstates < event_next_event ) { /* Profiler */ CHECK( profile, profile_active ) profile_map( PC ); END_CHECK /* If we're due an end of frame from RZX playback, generate one */ CHECK( rzx, rzx_playback ) if( R + rzx_instructions_offset >= rzx_instruction_count ) { event_add( tstates, spectrum_frame_event ); break; /* And break out of the execution loop to let the interrupt happen */ } END_CHECK /* Check if the debugger should become active at this point */ CHECK( debugger, debugger_mode != DEBUGGER_MODE_INACTIVE ) if( !z80.halted && debugger_check( DEBUGGER_BREAKPOINT_TYPE_EXECUTE, PC ) ) debugger_trap(); END_CHECK CHECK( beta, beta_available ) #define NOT_128_TYPE_OR_IS_48_TYPE ( !( machine_current->capabilities & \ LIBSPECTRUM_MACHINE_CAPABILITY_128_MEMORY ) || \ machine_current->ram.current_rom ) if( beta_active ) { if( NOT_128_TYPE_OR_IS_48_TYPE && PC >= 16384 ) { beta_unpage(); } } else if( ( PC & beta_pc_mask ) == beta_pc_value && NOT_128_TYPE_OR_IS_48_TYPE ) { beta_page(); } END_CHECK CHECK( plusd, plusd_available ) if( PC == 0x0008 || PC == 0x003a || PC == 0x0066 || PC == 0x028e ) { plusd_page(); } END_CHECK CHECK( didaktik80, didaktik80_available ) if( PC == 0x0000 || PC == 0x0008 ) { didaktik80_page(); } else if( PC == 0x1700 ) { didaktik80_unpage(); } END_CHECK CHECK( disciple, disciple_available ) if( PC == 0x0001 || PC == 0x0008 || PC == 0x0066 || PC == 0x028e ) { disciple_page(); } END_CHECK CHECK( usource, usource_available ) if( PC == 0x2bae ) { usource_toggle(); } END_CHECK CHECK( if1p, if1_available ) if( PC == 0x0008 || PC == 0x1708 ) { if1_page(); } END_CHECK CHECK( divide_early, settings_current.divide_enabled ) if( ( PC & 0xff00 ) == 0x3d00 ) { divide_set_automap( 1 ); } END_CHECK CHECK( spectranet_page, spectranet_available && !settings_current.spectranet_disable ) if( PC == 0x0008 || ((PC & 0xfff8) == 0x3ff8) ) spectranet_page( 0 ); if( PC == spectranet_programmable_trap && spectranet_programmable_trap_active ) event_add( 0, z80_nmi_event ); END_CHECK opcode_delay: contend_read( PC, 4 ); /* Check to see if M1 cycles happen on even tstates */ CHECK( evenm1, even_m1 ) if( tstates & 1 ) { if( ++tstates == event_next_event ) { break; } } END_CHECK run_opcode: /* Do the instruction fetch; readbyte_internal used here to avoid triggering read breakpoints */ opcode = readbyte_internal( PC ); CHECK( if1u, if1_available ) if( PC == 0x0700 ) { if1_unpage(); } END_CHECK CHECK( divide_late, settings_current.divide_enabled ) if( ( PC & 0xfff8 ) == 0x1ff8 ) { divide_set_automap( 0 ); } else if( (PC == 0x0000) || (PC == 0x0008) || (PC == 0x0038) || (PC == 0x0066) || (PC == 0x04c6) || (PC == 0x0562) ) { divide_set_automap( 1 ); } END_CHECK CHECK( opus, opus_available ) if( opus_active ) { if( PC == 0x1748 ) { opus_unpage(); } } else if( PC == 0x0008 || PC == 0x0048 || PC == 0x1708 ) { opus_page(); } END_CHECK CHECK( spectranet_unpage, spectranet_available ) if( PC == 0x007c ) spectranet_unpage(); END_CHECK CHECK( z80_halted, z80.halted ) /* Opcode read from memory is ignored and PC is left unchanged */ R++; continue; END_CHECK CHECK( z80_iff2_read, z80.iff2_read ) z80.iff2_read = 0; /* Execute *one* instruction before reevaluating the checks */ event_add( tstates, z80_nmos_iff2_event ); END_CHECK CHECK( didaktik80snap, didaktik80_snap ) if( PC == 0x0066 && !didaktik80_active ) { opcode = 0xc7; /* RST 00 */ didaktik80_snap = 0; /* FIXME: this should be a time-based reset */ } END_CHECK CHECK( svg_capture, svg_capture_active ) svg_capture(); END_CHECK end_opcode: PC++; R++; switch(opcode) { #include "z80/opcodes_base.c" } } }