Index: project
===================================================================
--- .cproject	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,72 +1,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
-	<storageModule moduleId="org.eclipse.cdt.core.settings">
-		<cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1082343239">
-			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.1082343239" moduleId="org.eclipse.cdt.core.settings" name="Default">
-				<externalSettings/>
-				<extensions>
-					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
-					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
-					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
-					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
-					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
-					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
-				</extensions>
-			</storageModule>
-			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
-				<configuration buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.base.1082343239" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
-					<folderInfo id="cdt.managedbuild.toolchain.gnu.base.1082343239.709608451" name="/" resourcePath="">
-						<toolChain id="cdt.managedbuild.toolchain.gnu.base.856845865" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
-							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.507363262" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
-							<builder id="cdt.managedbuild.target.gnu.builder.base.1177217740" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/>
-							<tool id="cdt.managedbuild.tool.gnu.archiver.base.410837344" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
-							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1860018834" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
-								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1709263588" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
-							</tool>
-							<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.862022870" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
-								<option id="gnu.c.compiler.option.include.paths.2032588655" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/buchla-emu/cpu}&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/buchla-emu/emu}&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/buchla-emu/build}&quot;"/>
-									<listOptionValue builtIn="false" value="/opt/sdl2/include"/>
-									<listOptionValue builtIn="false" value="/opt/rtmidi/include"/>
-								</option>
-								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1138147073" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
-							</tool>
-							<tool id="cdt.managedbuild.tool.gnu.c.linker.base.1271658493" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
-							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.38585950" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
-								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1749377136" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
-									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
-									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
-								</inputType>
-							</tool>
-							<tool id="cdt.managedbuild.tool.gnu.assembler.base.1567030630" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
-								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.874219201" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
-							</tool>
-						</toolChain>
-					</folderInfo>
-					<sourceEntries>
-						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="build"/>
-						<entry excluding="m68k_in.c" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="cpu"/>
-						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="emu"/>
-					</sourceEntries>
-				</configuration>
-			</storageModule>
-			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
-		</cconfiguration>
-	</storageModule>
-	<storageModule moduleId="cdtBuildSystem" version="4.0.0">
-		<project id="buchla-emu.null.1048337844" name="buchla-emu"/>
-	</storageModule>
-	<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
-	<storageModule moduleId="scannerConfiguration">
-		<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
-		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.1082343239;cdt.managedbuild.toolchain.gnu.base.1082343239.709608451;cdt.managedbuild.tool.gnu.cpp.compiler.base.1860018834;cdt.managedbuild.tool.gnu.cpp.compiler.input.1709263588">
-			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
-		</scannerConfigBuildInfo>
-		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.1082343239;cdt.managedbuild.toolchain.gnu.base.1082343239.709608451;cdt.managedbuild.tool.gnu.c.compiler.base.862022870;cdt.managedbuild.tool.gnu.c.compiler.input.1138147073">
-			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
-		</scannerConfigBuildInfo>
-	</storageModule>
-	<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
-</cproject>
Index: itignore
===================================================================
--- .gitignore	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,12 +1,0 @@
-bios.abs
-bios.elf
-midas.abs
-midas.elf
-
-build/*
-buchla
-buchla.exe
-mkdisk
-mkdisk.exe
-
-buchla.disk
Index: roject
===================================================================
--- .project	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,27 +1,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>buchla-emu</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
-			<triggers>clean,full,incremental,</triggers>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
-			<triggers>full,incremental,</triggers>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.cdt.core.cnature</nature>
-		<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
-		<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
-		<nature>org.eclipse.cdt.core.ccnature</nature>
-	</natures>
-</projectDescription>
Index: ettings/language.settings.xml
===================================================================
--- .settings/language.settings.xml	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,15 +1,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<project>
-	<configuration id="cdt.managedbuild.toolchain.gnu.base.1082343239" name="Default">
-		<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
-			<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
-			<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
-			<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
-			<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="882153106844088736" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
-				<language-scope id="org.eclipse.cdt.core.gcc"/>
-				<language-scope id="org.eclipse.cdt.core.g++"/>
-			</provider>
-			<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
-		</extension>
-	</configuration>
-</project>
Index: ettings/org.eclipse.cdt.core.prefs
===================================================================
--- .settings/org.eclipse.cdt.core.prefs	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,165 +1,0 @@
-eclipse.preferences.version=1
-org.eclipse.cdt.core.code_formatter=org.eclipse.cdt.core.defaultCodeFormatter
-org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16
-org.eclipse.cdt.core.formatter.alignment_for_assignment=16
-org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=80
-org.eclipse.cdt.core.formatter.alignment_for_binary_expression=16
-org.eclipse.cdt.core.formatter.alignment_for_compact_if=16
-org.eclipse.cdt.core.formatter.alignment_for_conditional_expression=34
-org.eclipse.cdt.core.formatter.alignment_for_conditional_expression_chain=18
-org.eclipse.cdt.core.formatter.alignment_for_constructor_initializer_list=0
-org.eclipse.cdt.core.formatter.alignment_for_declarator_list=16
-org.eclipse.cdt.core.formatter.alignment_for_enumerator_list=48
-org.eclipse.cdt.core.formatter.alignment_for_expression_list=0
-org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer=16
-org.eclipse.cdt.core.formatter.alignment_for_member_access=0
-org.eclipse.cdt.core.formatter.alignment_for_overloaded_left_shift_chain=16
-org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration=16
-org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
-org.eclipse.cdt.core.formatter.brace_position_for_array_initializer=end_of_line
-org.eclipse.cdt.core.formatter.brace_position_for_block=end_of_line
-org.eclipse.cdt.core.formatter.brace_position_for_block_in_case=end_of_line
-org.eclipse.cdt.core.formatter.brace_position_for_method_declaration=next_line
-org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration=end_of_line
-org.eclipse.cdt.core.formatter.brace_position_for_switch=end_of_line
-org.eclipse.cdt.core.formatter.brace_position_for_type_declaration=end_of_line
-org.eclipse.cdt.core.formatter.comment.line_up_line_comment_in_blocks_on_first_column=false
-org.eclipse.cdt.core.formatter.comment.min_distance_between_code_and_line_comment=1
-org.eclipse.cdt.core.formatter.comment.never_indent_line_comments_on_first_column=true
-org.eclipse.cdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
-org.eclipse.cdt.core.formatter.compact_else_if=true
-org.eclipse.cdt.core.formatter.continuation_indentation=2
-org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer=2
-org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line=false
-org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header=false
-org.eclipse.cdt.core.formatter.indent_access_specifier_extra_spaces=0
-org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier=true
-org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header=false
-org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases=true
-org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header=false
-org.eclipse.cdt.core.formatter.indent_empty_lines=false
-org.eclipse.cdt.core.formatter.indent_statements_compare_to_block=true
-org.eclipse.cdt.core.formatter.indent_statements_compare_to_body=true
-org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases=true
-org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch=false
-org.eclipse.cdt.core.formatter.indentation.size=4
-org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
-org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration=do not insert
-org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
-org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
-org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
-org.eclipse.cdt.core.formatter.insert_new_line_before_colon_in_constructor_initializer_list=do not insert
-org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
-org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration=do not insert
-org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement=insert
-org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block=insert
-org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator=insert
-org.eclipse.cdt.core.formatter.insert_space_after_binary_operator=insert
-org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments=insert
-org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters=insert
-org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block=insert
-org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
-org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause=insert
-org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case=insert
-org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional=insert
-org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
-org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
-org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types=insert
-org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list=insert
-org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
-org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list=insert
-org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
-org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
-org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
-org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments=insert
-org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters=insert
-org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
-org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator=do not insert
-org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional=insert
-org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for=insert
-org.eclipse.cdt.core.formatter.insert_space_after_unary_operator=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator=insert
-org.eclipse.cdt.core.formatter.insert_space_before_binary_operator=insert
-org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
-org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional=insert
-org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block=insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration=insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification=insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for=insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if=insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
-org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while=insert
-org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional=insert
-org.eclipse.cdt.core.formatter.insert_space_before_semicolon=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
-org.eclipse.cdt.core.formatter.insert_space_before_unary_operator=do not insert
-org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
-org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets=do not insert
-org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification=do not insert
-org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
-org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
-org.eclipse.cdt.core.formatter.join_wrapped_lines=true
-org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false
-org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false
-org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=false
-org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false
-org.eclipse.cdt.core.formatter.lineSplit=100
-org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1
-org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true
-org.eclipse.cdt.core.formatter.tabulation.char=tab
-org.eclipse.cdt.core.formatter.tabulation.size=4
-org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false
Index: ettings/org.eclipse.cdt.ui.prefs
===================================================================
--- .settings/org.eclipse.cdt.ui.prefs	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,3 +1,0 @@
-eclipse.preferences.version=1
-formatter_profile=_Thomas 4
-formatter_settings_version=1
Index: kefile
===================================================================
--- Makefile	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,155 +1,0 @@
-OS :=			$(shell uname)
-
-ifndef WIN
-GCC :=			gcc
-GPP :=			g++
-SDL2 :=			/opt/sdl2
-RTMIDI :=		/opt/rtmidi
-EXT :=
-else
-GCC :=			x86_64-w64-mingw32-gcc
-GPP :=			x86_64-w64-mingw32-g++
-SDL2 :=			/opt/sdl2-win
-RTMIDI :=		/opt/rtmidi-win
-EXT :=			.exe
-endif
-
-SDL2_INC :=		$(SDL2)/include
-SDL2_LIB :=		$(SDL2)/lib
-
-RTMIDI_INC :=	$(RTMIDI)/include
-RTMIDI_LIB :=	$(RTMIDI)/lib
-
-FLAGS :=		-std=c99 -O2 -gdwarf-4
-
-FLAGS_CPU :=	$(FLAGS) -pthread -I cpu -I build
-
-FLAGS_EMU :=	$(FLAGS) -pthread \
-				-fno-strict-aliasing -fno-inline -fno-omit-frame-pointer \
-				-Wall -Wextra \
-				-Wpedantic -Wconversion -Wsign-conversion -Wshadow \
-				-Wstrict-prototypes -Wmissing-declarations -Wredundant-decls \
-				-I cpu -I emu -I build -I $(SDL2_INC) -I $(RTMIDI_INC)
-
-FLAGS_AUX :=	$(FLAGS) -Wall -Wextra \
-				-Wpedantic -Wconversion -Wsign-conversion -Wshadow \
-				-Wstrict-prototypes -Wmissing-declarations -Wredundant-decls
-
-ifndef WIN
-ifeq ($(OS), Linux)
-FLAGS_EMU +=	-D EMU_LINUX
-FLAGS_LNK :=	$(FLAGS) -pthread -Wall -Wextra
-LIBS :=			$(SDL2_LIB)/libSDL2.a \
-				$(SDL2_LIB)/libSDL2_net.a \
-				$(SDL2_LIB)/libSDL2_ttf.a \
-				$(SDL2_LIB)/libfreetype.a \
-				$(RTMIDI_LIB)/librtmidi.a \
-				-ldl -lm -lasound
-endif
-
-ifeq ($(OS), Darwin)
-FLAGS_EMU +=	-D EMU_OS_X
-FLAGS_LNK :=	$(FLAGS) -Wall -Wextra
-LIBS :=			$(SDL2_LIB)/libSDL2.a \
-				$(SDL2_LIB)/libSDL2_net.a \
-				$(SDL2_LIB)/libSDL2_ttf.a \
-				$(SDL2_LIB)/libfreetype.a \
-				$(RTMIDI_LIB)/librtmidi.a \
-				-framework AppKit \
-				-framework AudioToolbox \
-				-framework Carbon \
-				-framework CoreAudio \
-				-framework CoreFoundation \
-				-framework CoreGraphics \
-				-framework CoreMIDI \
-				-framework CoreVideo \
-				-framework ForceFeedback \
-				-framework IOKit \
-				-framework Metal \
-				-l iconv
-endif
-else
-FLAGS_EMU +=	-D EMU_WIN
-FLAGS_LNK :=	$(FLAGS) -Wall -Wextra -static
-LIBS :=			-l mingw32 \
-				$(SDL2_LIB)/libSDL2.a \
-				$(SDL2_LIB)/libSDL2main.a \
-				$(SDL2_LIB)/libSDL2_net.a \
-				$(SDL2_LIB)/libSDL2_ttf.a \
-				$(SDL2_LIB)/libfreetype.a \
-				$(RTMIDI_LIB)/librtmidi.a \
-				-l gdi32 \
-				-l imm32 \
-				-l iphlpapi \
-				-l ole32 \
-				-l oleaut32 \
-				-l version \
-				-l winmm \
-				-l ws2_32
-endif
-
-HEADERS :=		$(wildcard cpu/*.h) $(wildcard emu/*.h)
-
-all:			buchla$(EXT) buchla.disk
-
-build/gen:
-				gcc $(FLAGS) -o build/gen cpu/m68kmake.c
-
-GEN_C :=		m68kopac.c m68kopdm.c m68kopnz.c m68kops.c
-GEN_H :=		m68kops.h
-
-GEN_CP :=		$(GEN_C:%=build/%)
-GEN_HP :=		$(GEN_H:%=build/%)
-
-GEN_O :=		$(GEN_C:.c=.o)
-GEN_OP :=		$(GEN_O:%=build/%)
-
-$(GEN_CP) $(GEN_HP): \
-				build/gen
-				cd cpu; ../build/gen ../build
-
-build/%.o:		build/%.c $(HEADERS)
-				$(GCC) $(FLAGS_CPU) -c -o $@ $<
-
-CPU_C :=		m68kcpu.c m68kdasm.c
-CPU_O :=		$(CPU_C:.c=.o)
-CPU_OP :=		$(CPU_O:%=build/%)
-
-build/%.o:		cpu/%.c $(HEADERS) $(GEN_HP)
-				$(GCC) $(FLAGS_CPU) -c -o $@ $<
-
-EMU_C :=		main.c cpu.c vid.c fpu.c tim.c lcd.c ser.c mid.c fdd.c snd.c \
-				led.c kbd.c sdl.c gdb.c
-EMU_O :=		$(EMU_C:.c=.o)
-EMU_OP :=		$(EMU_O:%=build/%)
-
-build/%.o:		emu/%.c $(HEADERS)
-				$(GCC) $(FLAGS_EMU) -c -o $@ $<
-
-buchla$(EXT):	$(CPU_OP) $(GEN_OP)	$(EMU_OP)
-				$(GPP) $(FLAGS_LNK) -o buchla$(EXT) \
-				$(CPU_OP) $(GEN_OP) $(EMU_OP) \
-				$(LIBS)
-
-mkdisk$(EXT):	emu/mkdisk.c
-				$(GCC) $(FLAGS_AUX) -o mkdisk$(EXT) emu/mkdisk.c
-
-buchla.disk:	mkdisk$(EXT) midas.abs
-				./mkdisk$(EXT)
-
-run:			buchla$(EXT) buchla.disk
-				./buchla$(EXT) ${EMU_OPTS}
-
-val:			buchla$(EXT) buchla.disk
-				valgrind --leak-resolution=high --track-fds=yes --leak-check=full \
-				--show-reachable=yes --suppressions=misc/buchla.supp \
-				./buchla$(EXT) ${EMU_OPTS}
-
-pack:
-				./pack.sh
-
-clean:
-				rm -f build/gen build/*.c build/*.h build/*.o
-				rm -f buchla$(EXT)
-				rm -f mkdisk$(EXT)
-				rm -f buchla.disk
Index: pying.txt
===================================================================
--- copying.txt	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,102 +1,0 @@
-Emulator License
-----------------
-
-(Applicable to the source code in the "emu" subdirectory.)
-
-Copyright (C) 2017 The Contributors
-
-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 3 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.
-
-A copy of the GNU General Public License can be found in the file
-"gpl.txt" in the top directory of this repository.
-
-
-Musashi License
----------------
-
-(Applicable to the source code in the "cpu" subdirectory.)
-
-MUSASHI
-Version 3.4
-
-A portable Motorola M680x0 processor emulation engine.
-Copyright 1998-2001 Karl Stenerud. All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-Vera Sans Mono License
-----------------------
-
-(Applicable to the "vera.ttf" font file.)
-
-Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream
-Vera is a trademark of Bitstream, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the fonts accompanying this license ("Fonts") and associated
-documentation files (the "Font Software"), to reproduce and distribute
-the Font Software, including without limitation the rights to use,
-copy, merge, publish, distribute, and/or sell copies of the Font
-Software, and to permit persons to whom the Font Software is furnished
-to do so, subject to the following conditions:
-
-The above copyright and trademark notices and this permission notice
-shall be included in all copies of one or more of the Font Software
-typefaces.
-
-The Font Software may be modified, altered, or added to, and in
-particular the designs of glyphs or characters in the Fonts may be
-modified and additional glyphs or characters may be added to the
-Fonts, only if the fonts are renamed to names not containing either
-the words "Bitstream" or the word "Vera".
-
-This License becomes null and void to the extent applicable to Fonts
-or Font Software that has been modified and is distributed under the
-"Bitstream Vera" names.
-
-The Font Software may be sold as part of a larger software package but
-no copy of one or more of the Font Software typefaces may be sold by
-itself.
-
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
-BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL,
-OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT
-SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
-
-Except as contained in this notice, the names of Gnome, the Gnome
-Foundation, and Bitstream Inc., shall not be used in advertising or
-otherwise to promote the sale, use or other dealings in this Font
-Software without prior written authorization from the Gnome Foundation
-or Bitstream Inc., respectively. For further information, contact:
-fonts at gnome dot org.
Index: cpu/m68kconf.h
===================================================================
--- cpu/m68kconf.h	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ cpu/m68kconf.h	(revision 93280c23175951b9a7032ca929ca2cc0457af62d)
@@ -53,5 +53,5 @@
  */
 #ifndef M68K_COMPILE_FOR_MAME
-#define M68K_COMPILE_FOR_MAME      OPT_OFF
+#define M68K_COMPILE_FOR_MAME      OPT_ON
 #endif /* M68K_COMPILE_FOR_MAME */
 
@@ -65,7 +65,7 @@
 
 /* Turn ON if you want to use the following M68K variants */
-#define M68K_EMULATE_010            OPT_OFF
-#define M68K_EMULATE_EC020          OPT_OFF
-#define M68K_EMULATE_020            OPT_OFF
+#define M68K_EMULATE_010            OPT_ON
+#define M68K_EMULATE_EC020          OPT_ON
+#define M68K_EMULATE_020            OPT_ON
 
 
@@ -132,5 +132,5 @@
  * instruction.
  */
-#define M68K_INSTRUCTION_HOOK       OPT_ON
+#define M68K_INSTRUCTION_HOOK       OPT_OFF
 #define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function()
 
Index: cpu/m68kmake.c
===================================================================
--- cpu/m68kmake.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ cpu/m68kmake.c	(revision 93280c23175951b9a7032ca929ca2cc0457af62d)
@@ -650,5 +650,5 @@
 
 
-	for(op = g_opcode_input_table;op->name[0] != 0;op++)
+	for(op = g_opcode_input_table;op->name != NULL;op++)
 	{
 		if(	strcmp(name, op->name) == 0 &&
@@ -666,5 +666,5 @@
 	opcode_struct* op;
 
-	for(op = g_opcode_input_table;op->name[0] != 0;op++)
+	for(op = g_opcode_input_table;op->name != NULL;op++)
 	{
 		if(strcmp(op->name, "illegal") == 0)
Index: u/all.h
===================================================================
--- emu/all.h	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,182 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl-v3.txt" in the top directory of this repository.
- */
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <xmmintrin.h>
-
-#include <m68k.h>
-
-#include <SDL2/SDL.h>
-#include <SDL2/SDL_net.h>
-#include <SDL2/SDL_ttf.h>
-
-// XXX - work around RtMidi's C++-isms; remove when fixed in RtMidi
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wstrict-prototypes"
-
-typedef struct RtMidiWrapper RtMidiWrapper;
-
-#include <rtmidi/rtmidi_c.h>
-
-#pragma GCC diagnostic pop
-
-#define inf(...) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__);
-#define err(...) SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__);
-
-#define _ver(_v, _t, ...) { \
-	if (_v > _t) { \
-		SDL_LogVerbose(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__); \
-	} \
-}
-
-#define fail(...) { \
-	SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__); \
-	exit(1); \
-}
-
-#define ARRAY_COUNT(_a) (int32_t)(sizeof (_a) / sizeof (_a)[0])
-
-extern int32_t sdl_verbose;
-extern int32_t gdb_verbose;
-extern int32_t cpu_verbose;
-extern int32_t fpu_verbose;
-extern int32_t vid_verbose;
-extern int32_t tim_verbose;
-extern int32_t lcd_verbose;
-extern int32_t ser_verbose;
-extern int32_t mid_verbose;
-extern int32_t fdd_verbose;
-extern int32_t snd_verbose;
-extern int32_t led_verbose;
-extern int32_t kbd_verbose;
-
-extern const char *bios;
-extern const char *disk;
-extern const char *font;
-
-extern uint32_t mid_port;
-
-extern SDL_atomic_t run;
-
-extern uint32_t vid_win;
-extern uint32_t ser_win;
-extern uint32_t lcd_win;
-
-extern void sdl_init(void);
-extern void sdl_quit(void);
-extern void sdl_loop(void);
-
-extern void gdb_init(void);
-extern void gdb_quit(void);
-extern void gdb_loop(void);
-extern void gdb_inst(bool bp);
-
-extern SDL_mutex *cpu_mutex;
-
-extern void cpu_init(void);
-extern void cpu_quit(void);
-extern void cpu_loop(void);
-
-extern uint8_t cpu_peek(int32_t addr);
-extern void cpu_poke(int32_t addr, uint8_t val);
-
-extern void fpu_init(void);
-extern void fpu_quit(void);
-extern bool fpu_exec(void);
-extern uint32_t fpu_read(uint32_t off, int32_t sz);
-extern void fpu_write(uint32_t off, int32_t sz, uint32_t val);
-
-extern void vid_init(void);
-extern void vid_quit(void);
-extern bool vid_exec(void);
-extern uint32_t vid_read(uint32_t off, int32_t sz);
-extern void vid_write(uint32_t off, int32_t sz, uint32_t val);
-
-extern void vid_sdl(void);
-
-extern void tim_init(void);
-extern void tim_quit(void);
-extern bool tim_exec(void);
-extern uint32_t tim_read(uint32_t off, int32_t sz);
-extern void tim_write(uint32_t off, int32_t sz, uint32_t val);
-
-extern void lcd_init(void);
-extern void lcd_quit(void);
-extern bool lcd_exec(void);
-extern uint32_t lcd_read(uint32_t off, int32_t sz);
-extern void lcd_write(uint32_t off, int32_t sz, uint32_t val);
-
-extern void lcd_sdl(void);
-
-extern void ser_init(void);
-extern void ser_quit(void);
-extern bool ser_exec(void);
-extern uint32_t ser_read(uint32_t off, int32_t sz);
-extern void ser_write(uint32_t off, int32_t sz, uint32_t val);
-
-extern void ser_sdl(void);
-extern void ser_text(SDL_TextInputEvent *ev);
-extern void ser_key(SDL_KeyboardEvent *ev);
-
-extern void ser_mou_res(void);
-extern void ser_mou_mov(SDL_MouseMotionEvent *ev);
-extern void ser_mou_dn(SDL_MouseButtonEvent *ev);
-extern void ser_mou_up(SDL_MouseButtonEvent *ev);
-
-extern void mid_init(void);
-extern void mid_quit(void);
-extern bool mid_exec(void);
-extern uint32_t mid_read(uint32_t off, int32_t sz);
-extern void mid_write(uint32_t off, int32_t sz, uint32_t val);
-extern void mid_list(void);
-
-extern void fdd_init(void);
-extern void fdd_quit(void);
-extern bool fdd_exec(void);
-extern uint32_t fdd_read(uint32_t off, int32_t sz);
-extern void fdd_write(uint32_t off, int32_t sz, uint32_t val);
-
-extern void fdd_set_side(int32_t sid);
-extern void fdd_set_sel(int32_t sel);
-
-extern void snd_init(void);
-extern void snd_quit(void);
-extern bool snd_exec(void);
-extern uint32_t snd_read(uint32_t off, int32_t sz);
-extern void snd_write(uint32_t off, int32_t sz, uint32_t val);
-
-extern void led_init(void);
-extern void led_quit(void);
-extern bool led_exec(void);
-extern uint32_t led_read(uint32_t off, int32_t sz);
-extern void led_write(uint32_t off, int32_t sz, uint32_t val);
-
-extern void kbd_init(void);
-extern void kbd_quit(void);
-extern bool kbd_exec(void);
-extern uint32_t kbd_read(uint32_t off, int32_t sz);
-extern void kbd_write(uint32_t off, int32_t sz, uint32_t val);
-
-extern void kbd_key(SDL_KeyboardEvent *ev, bool vid, bool dn);
Index: u/cpu.c
===================================================================
--- emu/cpu.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,772 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <all.h>
-
-#define ver(...) _ver(cpu_verbose, 0, __VA_ARGS__)
-#define ver2(...) _ver(cpu_verbose, 1, __VA_ARGS__)
-#define ver3(...) _ver(cpu_verbose, 2, __VA_ARGS__)
-
-int32_t cpu_verbose = 0;
-
-#define MIDAS_ABS "midas.abs"
-
-#define CPU_FREQ 7000000
-#define PER_SEC 100000
-
-#define APP_START 0x10000
-
-#define RAM_START 0x0
-#define RAM_SIZE 0x100000
-
-#define ROM_START 0x100000
-#define ROM_SIZE 0x10000
-
-typedef void (*hw_init_t)(void);
-typedef void (*hw_quit_t)(void);
-typedef bool (*hw_exec_t)(void);
-typedef uint32_t (*hw_read_t)(uint32_t off, int32_t sz);
-typedef void (*hw_write_t)(uint32_t off, int32_t sz, uint32_t val);
-
-typedef struct {
-	uint32_t addr_beg;
-	uint32_t addr_end;
-	uint32_t irq;
-	hw_init_t init;
-	hw_quit_t quit;
-	hw_exec_t exec;
-	hw_read_t read;
-	hw_write_t write;
-} hw_t;
-
-typedef struct {
-	uint32_t text_loc;
-	uint32_t text_len;
-	uint32_t data_loc;
-	uint32_t data_len;
-	uint32_t bss_loc;
-	uint32_t bss_len;
-	size_t load_len;
-	SDL_RWops *ops;
-} abs_t;
-
-static uint64_t freq;
-static uint64_t quan;
-
-SDL_mutex *cpu_mutex;
-
-static bool reset = true;
-
-static uint8_t ram_data[RAM_SIZE];
-static uint8_t rom_data[ROM_SIZE];
-
-static uint32_t ram_ro_beg = 0x1234;
-static uint32_t ram_ro_end = 0x1234;
-static uint32_t ram_rw_beg = 0x1234;
-static uint32_t ram_rw_end = 0x1234;
-
-static uint32_t rom_ro_beg;
-static uint32_t rom_ro_end;
-static uint32_t rom_rw_beg;
-static uint32_t rom_rw_end;
-
-static hw_t hw_map[] = {
-	{ 0x180000, 0x200000, 0, fpu_init, fpu_quit, fpu_exec, fpu_read, fpu_write },
-	{ 0x200000, 0x280002, 1, vid_init, vid_quit, vid_exec, vid_read, vid_write },
-	{ 0x3a0001, 0x3a4001, 4, tim_init, tim_quit, tim_exec, tim_read, tim_write },
-	{ 0x3a4001, 0x3a8001, 0, lcd_init, lcd_quit, lcd_exec, lcd_read, lcd_write },
-	{ 0x3a8001, 0x3ac001, 5, ser_init, ser_quit, ser_exec, ser_read, ser_write },
-	{ 0x3ac001, 0x3b0001, 5, mid_init, mid_quit, mid_exec, mid_read, mid_write },
-	{ 0x3b0001, 0x3b4001, 0, fdd_init, fdd_quit, fdd_exec, fdd_read, fdd_write },
-	{ 0x3b4001, 0x3b8001, 0, snd_init, snd_quit, snd_exec, snd_read, snd_write },
-	{ 0x3b8001, 0x3bc001, 0, led_init, led_quit, led_exec, led_read, led_write },
-	{ 0x3bc001, 0x3c0001, 3, kbd_init, kbd_quit, kbd_exec, kbd_read, kbd_write }
-};
-
-static hw_t *hw_by_addr(uint32_t addr)
-{
-	for (int32_t i = 0; i < ARRAY_COUNT(hw_map); ++i) {
-		if (addr >= hw_map[i].addr_beg && addr < hw_map[i].addr_end) {
-			return hw_map + i;
-		}
-	}
-
-	return NULL;
-}
-
-static void hw_init(void)
-{
-	inf("starting hardware");
-
-	for (int32_t i = 0; i < ARRAY_COUNT(hw_map); ++i) {
-		hw_map[i].init();
-	}
-}
-
-static void hw_quit(void)
-{
-	inf("halting hardware");
-
-	for (int32_t i = 0; i < ARRAY_COUNT(hw_map); ++i) {
-		hw_map[i].quit();
-	}
-}
-
-static uint32_t hw_exec(void)
-{
-	uint32_t irq = 0;
-
-	for (int32_t i = 0; i < ARRAY_COUNT(hw_map); ++i) {
-		if (hw_map[i].exec() && hw_map[i].irq > irq) {
-			irq = hw_map[i].irq;
-		}
-	}
-
-	return irq;
-}
-
-static uint32_t hw_off(hw_t *hw, uint32_t addr)
-{
-	if ((hw->addr_beg & 0x1) == 0) {
-		return addr - hw->addr_beg;
-	}
-
-	return (addr - hw->addr_beg) / 2;
-}
-
-static void open_abs(const char *path, abs_t *abs)
-{
-	abs->ops = SDL_RWFromFile(path, "rb");
-
-	if (abs->ops == NULL) {
-		fail("error while opening .abs file %s", path);
-	}
-
-	if (SDL_ReadBE16(abs->ops) != 0x601b) {
-		fail("invalid .abs file %s", path);
-	}
-
-	abs->text_len = SDL_ReadBE32(abs->ops);
-	abs->data_len = SDL_ReadBE32(abs->ops);
-	abs->bss_len = SDL_ReadBE32(abs->ops);
-
-	SDL_ReadBE32(abs->ops);
-	SDL_ReadBE32(abs->ops);
-
-	abs->text_loc = SDL_ReadBE32(abs->ops);
-
-	SDL_ReadBE16(abs->ops);
-
-	abs->data_loc = SDL_ReadBE32(abs->ops);
-	abs->bss_loc = SDL_ReadBE32(abs->ops);
-
-	inf("text 0x%x:0x%x data 0x%x:0x%x bss 0x%x:0x%x",
-			abs->text_loc, abs->text_len, abs->data_loc, abs->data_len, abs->bss_loc, abs->bss_len);
-
-	abs->load_len = (size_t)SDL_RWsize(abs->ops) - 36;
-}
-
-static void load_abs(const char *path, abs_t *abs, uint8_t *data)
-{
-	size_t loaded = 0;
-
-	while (loaded < abs->load_len) {
-		size_t n_rd = SDL_RWread(abs->ops, data + loaded, 1, abs->load_len - loaded);
-
-		if (n_rd == 0) {
-			fail("error while reading .abs file %s", path);
-		}
-
-		loaded += n_rd;
-	}
-
-	SDL_RWclose(abs->ops);
-}
-
-static void bios_init(void)
-{
-	inf("loading BIOS file %s", bios);
-
-	abs_t abs;
-	open_abs(bios, &abs);
-
-	if (abs.text_loc != ROM_START || abs.text_loc + abs.text_len != abs.data_loc ||
-			abs.load_len != abs.text_len + abs.data_len || abs.load_len > ROM_SIZE) {
-		fail("invalid BIOS file %s", bios);
-	}
-
-	load_abs(bios, &abs, rom_data);
-
-	rom_ro_beg = abs.text_loc;
-	rom_ro_end = abs.text_loc + abs.text_len + abs.data_len;
-	rom_rw_beg = abs.bss_loc;
-	rom_rw_end = abs.bss_loc + abs.bss_len;
-
-	ver("rom_ro_beg 0x%08x rom_ro_end 0x%08x", rom_ro_beg, rom_ro_end);
-	ver("rom_rw_beg 0x%08x rom_rw_end 0x%08x", rom_rw_beg, rom_rw_end);
-}
-
-static void midas_init(void)
-{
-	SDL_RWops *ops = SDL_RWFromFile(MIDAS_ABS, "rb");
-
-	if (ops == NULL) {
-		return;
-	}
-
-	SDL_RWclose(ops);
-
-	inf("loading MIDAS file " MIDAS_ABS);
-
-	abs_t abs;
-	open_abs(MIDAS_ABS, &abs);
-
-	if (abs.text_loc != APP_START ||
-			abs.text_loc + abs.text_len != abs.data_loc ||
-			abs.data_loc + abs.data_len != abs.bss_loc ||
-			abs.load_len != abs.text_len + abs.data_len ||
-			abs.bss_loc + abs.bss_len > RAM_SIZE) {
-		fail("invalid MIDAS file " MIDAS_ABS);
-	}
-
-	load_abs(MIDAS_ABS, &abs, ram_data + APP_START - RAM_START);
-
-	ram_ro_beg = ram_rw_beg = APP_START;
-	ram_ro_end = ram_rw_end = RAM_START + RAM_SIZE;
-}
-
-uint32_t m68k_read_disassembler_8(uint32_t addr)
-{
-	return m68k_read_memory_8(addr);
-}
-
-uint32_t m68k_read_disassembler_16(uint32_t addr)
-{
-	return m68k_read_memory_16(addr);
-}
-
-uint32_t m68k_read_disassembler_32(uint32_t addr)
-{
-	return m68k_read_memory_32(addr);
-}
-
-uint32_t m68k_read_memory_8(uint32_t addr)
-{
-	ver3("mem rd 0x%08x:8", addr);
-
-	if (addr >= ram_ro_beg && addr <= ram_ro_end - 1) {
-		return ram_data[addr - RAM_START];
-	}
-
-	if (addr >= ram_rw_beg && addr <= ram_rw_end - 1) {
-		return ram_data[addr - RAM_START];
-	}
-
-	if (addr >= rom_ro_beg && addr <= rom_ro_end - 1) {
-		return rom_data[addr - ROM_START];
-	}
-
-	if (addr >= rom_rw_beg && addr <= rom_rw_end - 1) {
-		// ROM has its BSS section in RAM.
-		return ram_data[addr - RAM_START];
-	}
-
-	hw_t *hw = hw_by_addr(addr);
-
-	if (hw != NULL) {
-		return hw->read(hw_off(hw, addr), 1);
-	}
-
-	if (addr <= APP_START - 1) {
-		return ram_data[addr];
-	}
-
-	fail("invalid read 0x%08x:8", addr);
-}
-
-uint32_t m68k_read_memory_16(uint32_t addr)
-{
-	ver3("mem rd 0x%08x:16", addr);
-
-	if (addr >= ram_ro_beg && addr <= ram_ro_end - 2) {
-		return
-				((uint32_t)ram_data[addr - RAM_START + 0] << 8) |
-				((uint32_t)ram_data[addr - RAM_START + 1] << 0);
-	}
-
-	if (addr >= ram_rw_beg && addr <= ram_rw_end - 2) {
-		return
-				((uint32_t)ram_data[addr - RAM_START + 0] << 8) |
-				((uint32_t)ram_data[addr - RAM_START + 1] << 0);
-	}
-
-	if (addr >= rom_ro_beg && addr <= rom_ro_end - 2) {
-		return
-				((uint32_t)rom_data[addr - ROM_START + 0] << 8) |
-				((uint32_t)rom_data[addr - ROM_START + 1] << 0);
-	}
-
-	if (addr >= rom_rw_beg && addr <= rom_rw_end - 2) {
-		// ROM has its BSS section in RAM.
-		return
-				((uint32_t)ram_data[addr - RAM_START + 0] << 8) |
-				((uint32_t)ram_data[addr - RAM_START + 1] << 0);
-	}
-
-	hw_t *hw = hw_by_addr(addr);
-
-	if (hw != NULL) {
-		return hw->read(hw_off(hw, addr), 2);
-	}
-
-	if (addr <= APP_START - 2) {
-		return
-				((uint32_t)ram_data[addr + 0] << 8) |
-				((uint32_t)ram_data[addr + 1] << 0);
-	}
-
-	fail("invalid read 0x%08x:16", addr);
-}
-
-uint32_t m68k_read_memory_32(uint32_t addr)
-{
-	ver3("mem rd 0x%08x:32", addr);
-
-	if (reset) {
-		if (addr == 0) {
-			addr += ROM_START;
-		}
-		else if (addr == 4) {
-			addr += ROM_START;
-			reset = false;
-		}
-		else {
-			fail("invalid reset sequence");
-		}
-	}
-
-	if (addr >= ram_ro_beg && addr <= ram_ro_end - 4) {
-		return
-				((uint32_t)ram_data[addr - RAM_START + 0] << 24) |
-				((uint32_t)ram_data[addr - RAM_START + 1] << 16) |
-				((uint32_t)ram_data[addr - RAM_START + 2] <<  8) |
-				((uint32_t)ram_data[addr - RAM_START + 3] <<  0);
-	}
-
-	if (addr >= ram_rw_beg && addr <= ram_rw_end - 4) {
-		return
-				((uint32_t)ram_data[addr - RAM_START + 0] << 24) |
-				((uint32_t)ram_data[addr - RAM_START + 1] << 16) |
-				((uint32_t)ram_data[addr - RAM_START + 2] <<  8) |
-				((uint32_t)ram_data[addr - RAM_START + 3] <<  0);
-	}
-
-	if (addr >= rom_ro_beg && addr <= rom_ro_end - 4) {
-		return
-				((uint32_t)rom_data[addr - ROM_START + 0] << 24) |
-				((uint32_t)rom_data[addr - ROM_START + 1] << 16) |
-				((uint32_t)rom_data[addr - ROM_START + 2] <<  8) |
-				((uint32_t)rom_data[addr - ROM_START + 3] <<  0);
-	}
-
-	if (addr >= rom_rw_beg && addr <= rom_rw_end - 4) {
-		// ROM has its BSS section in RAM.
-		return
-				((uint32_t)ram_data[addr - RAM_START + 0] << 24) |
-				((uint32_t)ram_data[addr - RAM_START + 1] << 16) |
-				((uint32_t)ram_data[addr - RAM_START + 2] <<  8) |
-				((uint32_t)ram_data[addr - RAM_START + 3] <<  0);
-	}
-
-	hw_t *hw = hw_by_addr(addr);
-
-	if (hw != NULL) {
-		return hw->read(hw_off(hw, addr), 4);
-	}
-
-	if (addr <= APP_START - 4) {
-		return
-				((uint32_t)ram_data[addr + 0] << 24) |
-				((uint32_t)ram_data[addr + 1] << 16) |
-				((uint32_t)ram_data[addr + 2] <<  8) |
-				((uint32_t)ram_data[addr + 3] <<  0);
-	}
-
-	fail("invalid read 0x%08x:32", addr);
-}
-
-void m68k_write_memory_8(uint32_t addr, uint32_t val)
-{
-	ver3("mem wr 0x%08x:8 0x%02x", addr, val);
-
-	if (addr >= ram_rw_beg && addr <= ram_rw_end - 1) {
-		ram_data[addr - RAM_START] = (uint8_t)val;
-		return;
-	}
-
-	if (addr >= rom_rw_beg && addr <= rom_rw_end - 1) {
-		// ROM has its BSS section in RAM.
-		ram_data[addr - RAM_START] = (uint8_t)val;
-		return;
-	}
-
-	hw_t *hw = hw_by_addr(addr);
-
-	if (hw != NULL) {
-		hw->write(hw_off(hw, addr), 1, val);
-		return;
-	}
-
-	if (addr <= APP_START - 1) {
-		ram_data[addr] = (uint8_t)val;
-		return;
-	}
-
-	// once midas.abs gets loaded, activate RAM
-
-	if (addr == APP_START) {
-		ram_data[addr] = (uint8_t)val;
-		ram_rw_beg = APP_START;
-		ram_rw_end = RAM_START + RAM_SIZE;
-		return;
-	}
-
-	fail("invalid write 0x%08x:8 0x%02x", addr, val);
-}
-
-void m68k_write_memory_16(uint32_t addr, uint32_t val)
-{
-	ver3("mem wr 0x%08x:16 0x%04x", addr, val);
-
-	if (addr >= ram_rw_beg && addr <= ram_rw_end - 2) {
-		ram_data[addr - RAM_START + 0] = (uint8_t)(val >> 8);
-		ram_data[addr - RAM_START + 1] = (uint8_t)(val >> 0);
-		return;
-	}
-
-	if (addr >= rom_rw_beg && addr <= rom_rw_end - 2) {
-		// ROM has its BSS section in RAM.
-		ram_data[addr - RAM_START + 0] = (uint8_t)(val >> 8);
-		ram_data[addr - RAM_START + 1] = (uint8_t)(val >> 0);
-		return;
-	}
-
-	hw_t *hw = hw_by_addr(addr);
-
-	if (hw != NULL) {
-		hw->write(hw_off(hw, addr), 2, val);
-		return;
-	}
-
-	if (addr <= APP_START - 2) {
-		ram_data[addr + 0] = (uint8_t)(val >> 8);
-		ram_data[addr + 1] = (uint8_t)(val >> 0);
-		return;
-	}
-
-	fail("invalid write 0x%08x:16 0x%04x", addr, val);
-}
-
-void m68k_write_memory_32(uint32_t addr, uint32_t val)
-{
-	ver3("mem wr 0x%08x:32 0x%08x", addr, val);
-
-	if (addr >= ram_rw_beg && addr <= ram_rw_end - 4) {
-		ram_data[addr - RAM_START + 0] = (uint8_t)(val >> 24);
-		ram_data[addr - RAM_START + 1] = (uint8_t)(val >> 16);
-		ram_data[addr - RAM_START + 2] = (uint8_t)(val >>  8);
-		ram_data[addr - RAM_START + 3] = (uint8_t)(val >>  0);
-		return;
-	}
-
-	if (addr >= rom_rw_beg && addr <= rom_rw_end - 4) {
-		// ROM has its BSS section in RAM.
-		ram_data[addr - RAM_START + 0] = (uint8_t)(val >> 24);
-		ram_data[addr - RAM_START + 1] = (uint8_t)(val >> 16);
-		ram_data[addr - RAM_START + 2] = (uint8_t)(val >>  8);
-		ram_data[addr - RAM_START + 3] = (uint8_t)(val >>  0);
-		return;
-	}
-
-	hw_t *hw = hw_by_addr(addr);
-
-	if (hw != NULL) {
-		hw->write(hw_off(hw, addr), 4, val);
-		return;
-	}
-
-	if (addr <= APP_START - 4) {
-		ram_data[addr + 0] = (uint8_t)(val >> 24);
-		ram_data[addr + 1] = (uint8_t)(val >> 16);
-		ram_data[addr + 2] = (uint8_t)(val >>  8);
-		ram_data[addr + 3] = (uint8_t)(val >>  0);
-		return;
-	}
-
-	fail("invalid write 0x%08x:32 0x%08x", addr, val);
-}
-
-uint8_t cpu_peek(int32_t addr)
-{
-	if (addr >= RAM_START && addr <= RAM_START + RAM_SIZE - 1) {
-		return ram_data[addr - RAM_START];
-	}
-
-	if (addr >= ROM_START && addr <= ROM_START + ROM_SIZE - 1) {
-		return rom_data[addr - ROM_START];
-	}
-
-	return 0;
-}
-
-void cpu_poke(int32_t addr, uint8_t val)
-{
-	if (addr >= RAM_START && addr <= RAM_START + RAM_SIZE - 1) {
-		ram_data[addr - RAM_START] = val;
-	}
-
-	if (addr >= ROM_START && addr <= ROM_START + ROM_SIZE - 1) {
-		rom_data[addr - ROM_START] = val;
-	}
-}
-
-static void inst_cb(void)
-{
-	uint32_t pc = m68k_get_reg(NULL, M68K_REG_PC);
-	uint32_t op = m68k_read_memory_16(pc);
-
-	gdb_inst(op == 0x4e4f);
-
-	if (op == 0x4e4d) {
-		uint32_t sp = m68k_get_reg(NULL, M68K_REG_SP);
-		uint32_t fun = m68k_read_memory_16(sp);
-
-		switch (fun) {
-		case 1:
-			ver2("BIOS B_RDAV %u", m68k_read_memory_16(sp + 2));
-			break;
-
-		case 2:
-			ver2("BIOS B_GETC %u", m68k_read_memory_16(sp + 2));
-			break;
-
-		case 3:
-			ver2("BIOS B_PUTC %u %u",
-					m68k_read_memory_16(sp + 2),
-					m68k_read_memory_16(sp + 4));
-			break;
-
-		case 4:
-			ver2("BIOS B_RDWR %u 0x%08x %u %u %u",
-					m68k_read_memory_16(sp + 2),
-					m68k_read_memory_32(sp + 4),
-					m68k_read_memory_16(sp + 8),
-					m68k_read_memory_16(sp + 10),
-					m68k_read_memory_16(sp + 12));
-			break;
-
-		case 5:
-			ver2("BIOS B_SETV %u 0x%08x",
-					m68k_read_memory_16(sp + 2),
-					m68k_read_memory_32(sp + 4));
-			break;
-
-		case 7:
-			ver2("BIOS B_GBPB %u", m68k_read_memory_16(sp + 2));
-			break;
-
-		case 8:
-			ver2("BIOS B_THRE %u", m68k_read_memory_16(sp + 2));
-			break;
-
-		case 9:
-			ver2("BIOS B_MCHG %u", m68k_read_memory_16(sp + 2));
-			break;
-
-		case 10:
-			ver2("BIOS B_DMAP");
-			break;
-
-		default:
-			fail("invalid function: BIOS %d", fun);
-		}
-	}
-	else if (op == 0x4e4e) {
-		uint32_t sp = m68k_get_reg(NULL, M68K_REG_SP);
-		uint32_t fun = m68k_read_memory_16(sp);
-
-		switch (fun) {
-		case 0:
-			ver2("XBIOS X_PIOREC %u", m68k_read_memory_16(sp + 2));
-			break;
-
-		case 1:
-			ver2("XBIOS X_SETPRT %u 0x%02x 0x%02x 0x%02x 0x%02x",
-					m68k_read_memory_16(sp + 2),
-					m68k_read_memory_16(sp + 4),
-					m68k_read_memory_16(sp + 6),
-					m68k_read_memory_16(sp + 8),
-					m68k_read_memory_16(sp + 10));
-			break;
-
-		case 2:
-			ver2("XBIOS X_FLOPRD 0x%08x 0x%08x %u %u %u %u %u",
-					m68k_read_memory_32(sp + 2),
-					m68k_read_memory_32(sp + 6),
-					m68k_read_memory_16(sp + 10),
-					m68k_read_memory_16(sp + 12),
-					m68k_read_memory_16(sp + 14),
-					m68k_read_memory_16(sp + 16),
-					m68k_read_memory_16(sp + 18));
-			break;
-
-		case 3:
-			ver2("XBIOS X_FLOPWR 0x%08x 0x%08x %u %u %u %u %u",
-					m68k_read_memory_32(sp + 2),
-					m68k_read_memory_32(sp + 6),
-					m68k_read_memory_16(sp + 10),
-					m68k_read_memory_16(sp + 12),
-					m68k_read_memory_16(sp + 14),
-					m68k_read_memory_16(sp + 16),
-					m68k_read_memory_16(sp + 18));
-			break;
-
-		case 4:
-			ver2("XBIOS X_FORMAT 0x%08x 0x%08x %u %u %u %u %u 0x%08x %u",
-					m68k_read_memory_32(sp + 2),
-					m68k_read_memory_32(sp + 6),
-					m68k_read_memory_16(sp + 10),
-					m68k_read_memory_16(sp + 12),
-					m68k_read_memory_16(sp + 14),
-					m68k_read_memory_16(sp + 16),
-					m68k_read_memory_16(sp + 18),
-					m68k_read_memory_32(sp + 20),
-					m68k_read_memory_16(sp + 24));
-			break;
-
-		case 5:
-			ver2("XBIOS X_VERIFY 0x%08x 0x%08x %u %u %u %u %u",
-					m68k_read_memory_32(sp + 2),
-					m68k_read_memory_32(sp + 6),
-					m68k_read_memory_16(sp + 10),
-					m68k_read_memory_16(sp + 12),
-					m68k_read_memory_16(sp + 14),
-					m68k_read_memory_16(sp + 16),
-					m68k_read_memory_16(sp + 18));
-			break;
-
-		case 6:
-			ver2("XBIOS X_PRBOOT 0x%08x %u %u %u",
-					m68k_read_memory_32(sp + 2),
-					m68k_read_memory_16(sp + 6),
-					m68k_read_memory_16(sp + 8),
-					m68k_read_memory_16(sp + 10));
-			break;
-
-		case 7:
-			ver2("XBIOS X_RANDOM");
-			break;
-
-		case 8:
-			ver2("XBIOS X_ANALOG");
-			break;
-
-		case 9:
-			ver2("XBIOS X_CLRAFI");
-			break;
-
-		case 10:
-			ver2("XBIOS X_APICHK");
-			break;
-
-		case 11:
-			ver2("XBIOS X_MTDEFS ");
-			break;
-
-		default:
-			fail("invalid function: XBIOS %d", fun);
-		}
-	}
-}
-
-void cpu_init(void)
-{
-	cpu_mutex = SDL_CreateMutex();
-
-	if (cpu_mutex == NULL) {
-		fail("SDL_CreateMutex() failed: %s", SDL_GetError());
-	}
-
-	freq = SDL_GetPerformanceFrequency();
-	quan = freq / PER_SEC;
-
-	inf("freq %" PRIu64 " quan %" PRIu64, freq, quan);
-
-	hw_init();
-	bios_init();
-	midas_init();
-
-	m68k_init();
-	m68k_set_cpu_type(M68K_CPU_TYPE_68000);
-	m68k_set_instr_hook_callback(inst_cb);
-	m68k_pulse_reset();
-}
-
-void cpu_quit(void)
-{
-	hw_quit();
-	SDL_DestroyMutex(cpu_mutex);
-}
-
-void cpu_loop(void)
-{
-	inf("entering CPU loop");
-	int32_t count = 0;
-
-	while (SDL_AtomicGet(&run) != 0) {
-		uint64_t until = SDL_GetPerformanceCounter() + quan;
-
-		if (SDL_LockMutex(cpu_mutex) < 0) {
-			fail("SDL_LockMutex() failed: %s", SDL_GetError());
-		}
-
-		m68k_execute(CPU_FREQ / PER_SEC);
-		uint32_t irq = hw_exec();
-
-		if (irq > 0) {
-			ver2("irq %u", irq);
-		}
-
-		m68k_set_irq(irq);
-
-		if (SDL_UnlockMutex(cpu_mutex) < 0) {
-			fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-		}
-
-		if ((++count & 0x1ff) == 0) {
-			SDL_Delay(0);
-		}
-
-		while (SDL_GetPerformanceCounter() < until) {
-			for (int32_t i = 0; i < 100; ++i) {
-				_mm_pause();
-			}
-		}
-	}
-
-	inf("leaving CPU loop");
-}
Index: u/fdd.c
===================================================================
--- emu/fdd.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,417 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <all.h>
-
-#define ver(...) _ver(fdd_verbose, 0, __VA_ARGS__)
-#define ver2(...) _ver(fdd_verbose, 1, __VA_ARGS__)
-#define ver3(...) _ver(fdd_verbose, 2, __VA_ARGS__)
-
-int32_t fdd_verbose = 0;
-
-#define N_CYL 80
-#define N_SID 2
-#define N_SEC 9
-#define SZ_SEC 512
-
-#define SZ_DISK (N_CYL * N_SID * N_SEC * SZ_SEC)
-
-#define REG_COM_STAT 0
-#define REG_TRA 1
-#define REG_SEC 2
-#define REG_DAT 3
-
-#define COM_REST 0x00
-#define COM_SEEK 0x10
-#define COM_SEEK_VER 0x14
-#define COM_RD_SEC 0x80
-#define COM_RD_SEC_MUL 0x90
-#define COM_WR_SEC_WP 0xa0
-#define COM_WR_SEC 0xa2
-#define COM_INT 0xd0
-#define COM_WR_TRA_WP 0xf0
-#define COM_WR_TRA 0xf2
-
-#define COM_LAT_CYC 5
-#define COM_EXE_CYC 5
-
-typedef enum {
-	STEP_IDLE,
-	STEP_PREP,
-	STEP_EXEC
-} step_t;
-
-typedef struct {
-	int32_t reg_tra;
-	int32_t reg_sec;
-	int32_t reg_dat;
-	int32_t sid;
-	step_t step;
-	int32_t com;
-	int32_t cyc;
-	uint8_t *dat;
-	bool tra_0;
-} state_t;
-
-static state_t state = {
-		.reg_tra = 0, .reg_sec = 0, .reg_dat = 0, .sid = 0,
-		.step = STEP_IDLE, .com = -1, .cyc = 0, .dat = NULL, .tra_0 = false
-};
-
-static uint8_t image[SZ_DISK];
-
-static const char *com_string(int32_t com)
-{
-	switch (com) {
-	case COM_REST:
-		return "COM_REST";
-
-	case COM_SEEK:
-		return "COM_SEEK";
-
-	case COM_SEEK_VER:
-		return "COM_SEEK_VER";
-
-	case COM_RD_SEC:
-		return "COM_RD_SEC";
-
-	case COM_RD_SEC_MUL:
-		return "COM_RD_SEC_MUL";
-
-	case COM_WR_SEC_WP:
-		return "COM_WR_SEC_WP";
-
-	case COM_WR_SEC:
-		return "COM_WR_SEC";
-
-	case COM_WR_TRA_WP:
-		return "COM_WR_TRA_WP";
-
-	case COM_WR_TRA:
-		return "COM_WR_TRA";
-
-	default:
-		fail("unknown command 0x%02x", com);
-	}
-}
-
-static void stat_string(int32_t stat, char *buff) {
-	buff[0] = 0;
-
-	if ((stat & 0x80) != 0) {
-		strcat(buff, " mot_on");
-	}
-
-	if ((stat & 0x04) != 0) {
-		strcat(buff, " zero");
-	}
-
-	if ((stat & 0x02) != 0) {
-		strcat(buff, " dat_req");
-	}
-
-	if ((stat & 0x01) != 0) {
-		strcat(buff, " busy");
-	}
-}
-
-void fdd_set_side(int32_t sid)
-{
-	ver2("sid <- %d", sid);
-	state.sid = sid;
-}
-
-void fdd_set_sel(int32_t sel)
-{
-	ver2("sel <- %d", sel);
-}
-
-void fdd_init(void)
-{
-	ver("fdd init");
-	inf("reading disk image file %s", disk);
-
-	SDL_RWops *ops = SDL_RWFromFile(disk, "rb");
-
-	if (ops == NULL) {
-		fail("error while opening disk image file %s for reading", disk);
-	}
-
-	size_t loaded = 0;
-
-	while (loaded < SZ_DISK) {
-		size_t n_rd = SDL_RWread(ops, image + loaded, 1, SZ_DISK - loaded);
-
-		if (n_rd == 0) {
-			fail("error while reading disk image file %s", disk);
-		}
-
-		loaded += n_rd;
-	}
-
-	SDL_RWclose(ops);
-}
-
-void fdd_quit(void)
-{
-	ver("fdd quit");
-	inf("writing disk image file %s", disk);
-
-	SDL_RWops *ops = SDL_RWFromFile(disk, "wb");
-
-	if (ops == NULL) {
-		fail("error while opening disk image file %s for writing", disk);
-	}
-
-	size_t stored = 0;
-
-	while (stored < SZ_DISK) {
-		size_t n_wr = SDL_RWwrite(ops, image + stored, 1, SZ_DISK - stored);
-
-		if (n_wr == 0) {
-			fail("error while writing disk image file %s", disk);
-		}
-
-		stored += n_wr;
-	}
-
-	SDL_RWclose(ops);
-}
-
-bool fdd_exec(void)
-{
-	ver3("fdd exec");
-
-	switch (state.step) {
-	case STEP_IDLE:
-		break;
-
-	case STEP_PREP:
-		ver3("prep %d", state.cyc);
-		--state.cyc;
-
-		if (state.cyc == 0) {
-			ver2("exec %s", com_string(state.com));
-			state.step = STEP_EXEC;
-			state.cyc = COM_EXE_CYC;
-		}
-
-		break;
-
-	case STEP_EXEC:
-		ver3("exec %d", state.cyc);
-		--state.cyc;
-
-		if (state.cyc == 0) {
-			ver2("idle %s", com_string(state.com));
-			state.step = STEP_IDLE;
-		}
-
-		break;
-	}
-
-	return false;
-}
-
-uint32_t fdd_read(uint32_t off, int32_t sz)
-{
-	ver3("fdd rd %u:%d", off, sz * 8);
-
-	if (sz != 1 || off > 3) {
-		fail("invalid fdd rd %u:%d", off, sz * 8);
-	}
-
-	uint32_t rv;
-
-	switch (off) {
-	case REG_COM_STAT:
-		rv = 0x80; // motor on
-
-		if (state.step == STEP_EXEC) {
-			rv |= 0x01; // busy
-
-			switch (state.com) {
-			case COM_RD_SEC:
-			case COM_RD_SEC_MUL:
-			case COM_WR_SEC:
-			case COM_WR_SEC_WP:
-				rv |= 0x02; // data request
-				break;
-			}
-		}
-
-		if (state.tra_0) {
-			rv |= 0x04; // track zero
-		}
-
-		char stat[100];
-		stat_string((int32_t)rv, stat);
-		ver3("stat -> 0x%02x%s", rv, stat);
-		break;
-
-	case REG_TRA:
-		rv = (uint32_t)state.reg_tra;
-		ver2("tra -> %u", rv);
-		break;
-
-	case REG_SEC:
-		rv = (uint32_t)state.reg_sec;
-		ver2("sec -> %u", rv);
-		break;
-
-	case REG_DAT:
-		if (state.step != STEP_EXEC ||
-				(state.com != COM_RD_SEC && state.com != COM_RD_SEC_MUL)) {
-			fail("unexpected data register read");
-		}
-
-		rv = *state.dat;
-		int32_t addr = (int32_t)(state.dat - image);
-
-		if ((addr & (SZ_SEC - 1)) == 0) {
-			ver2("addr 0x%06x -> 0x%02x", addr, rv);
-		}
-		else {
-			ver3("addr 0x%06x -> 0x%02x", addr, rv);
-		}
-
-		++state.dat;
-		++addr;
-
-		if ((addr & (SZ_SEC - 1)) == 0 && state.com == COM_RD_SEC) {
-			state.step = STEP_IDLE;
-			state.cyc = 0;
-		}
-		else {
-			state.cyc = COM_EXE_CYC;
-		}
-
-		break;
-
-	default:
-		rv = 0;
-		break;
-	}
-
-	return rv;
-}
-
-void fdd_write(uint32_t off, int32_t sz, uint32_t val)
-{
-	ver3("fdd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
-
-	if (sz != 1 || off > 3) {
-		fail("invalid fdd wr %u:%d", off, sz * 8);
-	}
-
-	switch (off) {
-	case REG_COM_STAT:
-		ver2("com <- 0x%02x, tra %d, sid %d, sec %d",
-				val, state.reg_tra, state.sid, state.reg_sec);
-
-		state.com = (int32_t)val;
-
-		ver2("prep %s", com_string(state.com));
-		state.step = STEP_PREP;
-		state.cyc = COM_LAT_CYC;
-
-		switch (val) {
-		case COM_REST:
-			state.reg_tra = 0;
-			state.tra_0 = true;
-			state.dat = NULL;
-			break;
-
-		case COM_SEEK:
-		case COM_SEEK_VER:
-			state.reg_tra = state.reg_dat;
-			state.tra_0 = state.reg_tra == 0;
-			state.dat = NULL;
-			break;
-
-		case COM_RD_SEC:
-		case COM_RD_SEC_MUL:
-		case COM_WR_SEC:
-		case COM_WR_SEC_WP: {
-			size_t sec_off = (size_t)(((state.reg_tra * N_SID + state.sid) * N_SEC +
-					state.reg_sec - 1) * SZ_SEC);
-			state.dat = image + sec_off;
-			state.tra_0 = false;
-			break;
-		}
-
-		case COM_INT:
-			state.step = STEP_IDLE;
-			state.cyc = 0;
-			state.dat = NULL;
-			state.tra_0 = false;
-			break;
-
-		case COM_WR_TRA:
-		case COM_WR_TRA_WP:
-			state.tra_0 = false;
-			fail("format not yet supported");
-			break;
-		}
-
-		break;
-
-	case REG_TRA:
-		state.reg_tra = (int32_t)val;
-		ver2("tra <- %u", val);
-		break;
-
-	case REG_SEC:
-		state.reg_sec = (int32_t)val;
-		ver2("sec <- %u", val);
-		break;
-
-	case REG_DAT:
-		if (state.step == STEP_EXEC &&
-				(state.com == COM_WR_SEC || state.com == COM_WR_SEC_WP)) {
-			*state.dat = (uint8_t)val;
-			int32_t addr = (int32_t)(state.dat - image);
-
-			if ((addr & (SZ_SEC - 1)) == 0) {
-				ver2("addr 0x%06x <- 0x%02x", addr, val);
-			}
-			else {
-				ver3("addr 0x%06x <- 0x%02x", addr, val);
-			}
-
-			++state.dat;
-			++addr;
-
-			if ((addr & (SZ_SEC - 1)) == 0) {
-				state.step = STEP_IDLE;
-				state.cyc = 0;
-			}
-			else {
-				state.cyc = COM_EXE_CYC;
-			}
-		}
-		else {
-			state.reg_dat = (int32_t)val;
-			ver2("dat <- 0x%02x", val);
-		}
-
-		break;
-
-	default:
-		break;
-	}
-}
Index: u/fpu.c
===================================================================
--- emu/fpu.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,51 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <all.h>
-
-#define ver(...) _ver(fpu_verbose, 0, __VA_ARGS__)
-#define ver2(...) _ver(fpu_verbose, 1, __VA_ARGS__)
-#define ver3(...) _ver(fpu_verbose, 2, __VA_ARGS__)
-
-int32_t fpu_verbose = 0;
-
-void fpu_init(void)
-{
-	ver("fpu init");
-}
-
-void fpu_quit(void)
-{
-	ver("fpu quit");
-}
-
-bool fpu_exec(void)
-{
-	ver3("fpu exec");
-	return false;
-}
-
-uint32_t fpu_read(uint32_t off, int32_t sz)
-{
-	ver2("fpu rd 0x%04x:%d", off, sz * 8);
-	return 0;
-}
-
-void fpu_write(uint32_t off, int32_t sz, uint32_t val)
-{
-	ver2("fpu wr 0x%04x:%d 0x%0*x", off, sz * 8, sz * 2, val);
-}
Index: u/gdb.c
===================================================================
--- emu/gdb.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,696 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <all.h>
-
-#define ver(...) _ver(gdb_verbose, 0, __VA_ARGS__)
-#define ver2(...) _ver(gdb_verbose, 1, __VA_ARGS__)
-#define ver3(...) _ver(gdb_verbose, 2, __VA_ARGS__)
-
-int32_t gdb_verbose = 0;
-
-#define PORT 12053
-#define SZ_BUF 10000
-
-#define RES_ERR \
-	((result_t){ .ok = false })
-
-#define RES_OK \
-	((result_t){ .ok = true })
-
-#define RES_DAT(_out, _n_out) \
-	((result_t){ .ok = true, .out = (uint8_t *)_out, .n_out = (int32_t)_n_out })
-
-#define LOCK_NONE 0
-#define LOCK_REQ 1
-#define LOCK_ACK 2
-#define LOCK_BP 3
-
-typedef enum {
-	STATE_HEAD,
-	STATE_DATA,
-	STATE_CHECK_1,
-	STATE_CHECK_2,
-	STATE_ACK
-} state_t;
-
-typedef struct {
-	bool ok;
-	const uint8_t *out;
-	int32_t n_out;
-} result_t;
-
-static TCPsocket lis;
-static SDLNet_SocketSet set;
-
-static state_t state;
-static SDL_atomic_t lock;
-
-void gdb_init(void)
-{
-	ver("gdb init");
-
-	IPaddress addr;
-
-	if (SDLNet_ResolveHost(&addr, NULL, PORT) < 0) {
-		fail("SDLNet_ResolveHost() failed: %s", SDLNet_GetError());
-	}
-
-	lis = SDLNet_TCP_Open(&addr);
-
-	if (lis == NULL) {
-		fail("SDLNet_TCP_Open() failed: %s", SDLNet_GetError());
-	}
-
-	set = SDLNet_AllocSocketSet(2);
-
-	if (set == NULL) {
-		fail("SDLNet_AllocSocketSet() failed: %s", SDLNet_GetError());
-	}
-
-	if (SDLNet_TCP_AddSocket(set, lis) < 0) {
-		fail("SDLNet_AddSocket() failed: %s", SDLNet_GetError());
-	}
-
-	SDL_AtomicSet(&lock, 0);
-}
-
-void gdb_quit(void)
-{
-	ver("gdb quit");
-
-	SDLNet_FreeSocketSet(set);
-	SDLNet_TCP_Close(lis);
-}
-
-void gdb_inst(bool bp)
-{
-	ver3("gdb inst");
-
-	if (!bp && SDL_AtomicGet(&lock) == LOCK_NONE) {
-		return;
-	}
-
-	if (SDL_UnlockMutex(cpu_mutex) < 0) {
-		fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-	}
-
-	if (bp) {
-		ver2("-> lock bp");
-		SDL_AtomicSet(&lock, LOCK_BP);
-
-		while (SDL_AtomicGet(&lock) != LOCK_REQ) {
-			SDL_Delay(100);
-		}
-	}
-
-	ver2("<- lock req");
-	ver2("-> lock ack");
-	SDL_AtomicSet(&lock, LOCK_ACK);
-
-	while (SDL_AtomicGet(&lock) == LOCK_ACK) {
-		SDL_Delay(100);
-	}
-
-	ver2("<- lock none / req");
-
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-}
-
-static void wait_cpu(void)
-{
-	while (SDL_AtomicGet(&lock) != LOCK_ACK) {
-		SDL_Delay(100);
-	}
-
-	ver2("<- lock ack");
-}
-
-static void stop_cpu(void)
-{
-	ver2("-> lock req");
-	SDL_AtomicSet(&lock, LOCK_REQ);
-
-	wait_cpu();
-}
-
-static void cont_cpu(void)
-{
-	ver2("-> lock none");
-	SDL_AtomicSet(&lock, LOCK_NONE);
-}
-
-static int32_t hex_digit(char c)
-{
-	if (c >= '0' && c <= '9') {
-		return c - '0';
-	}
-
-	if (c >= 'a' && c <= 'f') {
-		return 10 + c - 'a';
-	}
-
-	if (c >= 'A' && c <= 'F') {
-		return 10 + c - 'A';
-	}
-
-	return -1;
-}
-
-static int32_t hex_num(const char **pp)
-{
-	int32_t res = 0;
-	int32_t dig;
-
-	while ((dig = hex_digit(**pp)) >= 0) {
-		res = (res << 4) | dig;
-		++*pp;
-	}
-
-	return res;
-}
-
-static result_t com_reason(void)
-{
-	// 0x05 = SIGTRAP
-	return RES_DAT("S05", 3);
-}
-
-static void set_pc(const char **req)
-{
-	int32_t addr = hex_num(req);
-
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	m68k_set_reg(M68K_REG_PC, (uint32_t)addr);
-
-	if (SDL_UnlockMutex(cpu_mutex) < 0) {
-		fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-	}
-}
-
-static result_t com_cont(const char *req)
-{
-	if (req[0] != 0) {
-		set_pc(&req);
-	}
-
-	cont_cpu();
-
-	return RES_OK;
-}
-
-static result_t com_step(const char *req)
-{
-	if (req[0] != 0) {
-		set_pc(&req);
-	}
-
-	stop_cpu();
-
-	// 0x05 = SIGTRAP
-	return RES_DAT("S05", 3);
-}
-
-static result_t com_rd_reg(void)
-{
-	static char buf[(8 + 8 + 2) * 8 + 1];
-
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	uint32_t d0 = m68k_get_reg(NULL, M68K_REG_D0);
-	uint32_t d1 = m68k_get_reg(NULL, M68K_REG_D1);
-	uint32_t d2 = m68k_get_reg(NULL, M68K_REG_D2);
-	uint32_t d3 = m68k_get_reg(NULL, M68K_REG_D3);
-	uint32_t d4 = m68k_get_reg(NULL, M68K_REG_D4);
-	uint32_t d5 = m68k_get_reg(NULL, M68K_REG_D5);
-	uint32_t d6 = m68k_get_reg(NULL, M68K_REG_D6);
-	uint32_t d7 = m68k_get_reg(NULL, M68K_REG_D7);
-
-	uint32_t a0 = m68k_get_reg(NULL, M68K_REG_A0);
-	uint32_t a1 = m68k_get_reg(NULL, M68K_REG_A1);
-	uint32_t a2 = m68k_get_reg(NULL, M68K_REG_A2);
-	uint32_t a3 = m68k_get_reg(NULL, M68K_REG_A3);
-	uint32_t a4 = m68k_get_reg(NULL, M68K_REG_A4);
-	uint32_t a5 = m68k_get_reg(NULL, M68K_REG_A5);
-	uint32_t a6 = m68k_get_reg(NULL, M68K_REG_A6);
-	uint32_t a7 = m68k_get_reg(NULL, M68K_REG_A7);
-
-	uint32_t ps = m68k_get_reg(NULL, M68K_REG_SR);
-	uint32_t pc = m68k_get_reg(NULL, M68K_REG_PC);
-
-	if (SDL_UnlockMutex(cpu_mutex) < 0) {
-		fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-	}
-
-	sprintf(buf,
-			"%08x%08x%08x%08x%08x%08x%08x%08x"
-			"%08x%08x%08x%08x%08x%08x%08x%08x"
-			"%08x%08x",
-			d0, d1, d2, d3, d4, d5, d6, d7,
-			a0, a1, a2, a3, a4, a5, a6, a7,
-			ps, pc);
-
-	return RES_DAT(buf, sizeof buf - 1);
-}
-
-static result_t com_wr_reg(const char *req)
-{
-	uint32_t d0, d1, d2, d3, d4, d5, d6, d7;
-	uint32_t a0, a1, a2, a3, a4, a5, a6, a7;
-	uint32_t ps, pc;
-
-	if (sscanf(req,
-			"%08x%08x%08x%08x%08x%08x%08x%08x"
-			"%08x%08x%08x%08x%08x%08x%08x%08x"
-			"%08x%08x",
-			&d0, &d1, &d2, &d3, &d4, &d5, &d6, &d7,
-			&a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7,
-			&ps, &pc) != 8 + 8 + 2) {
-		return RES_DAT("E01", 3);
-	}
-
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	m68k_set_reg(M68K_REG_D0, d0);
-	m68k_set_reg(M68K_REG_D1, d1);
-	m68k_set_reg(M68K_REG_D2, d2);
-	m68k_set_reg(M68K_REG_D3, d3);
-	m68k_set_reg(M68K_REG_D4, d4);
-	m68k_set_reg(M68K_REG_D5, d5);
-	m68k_set_reg(M68K_REG_D6, d6);
-	m68k_set_reg(M68K_REG_D7, d7);
-
-	m68k_set_reg(M68K_REG_A0, a0);
-	m68k_set_reg(M68K_REG_A1, a1);
-	m68k_set_reg(M68K_REG_A2, a2);
-	m68k_set_reg(M68K_REG_A3, a3);
-	m68k_set_reg(M68K_REG_A4, a4);
-	m68k_set_reg(M68K_REG_A5, a5);
-	m68k_set_reg(M68K_REG_A6, a6);
-	m68k_set_reg(M68K_REG_A7, a7);
-
-	m68k_set_reg(M68K_REG_SR, ps);
-	m68k_set_reg(M68K_REG_PC, pc);
-
-	if (SDL_UnlockMutex(cpu_mutex) < 0) {
-		fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-	}
-
-	return RES_DAT("OK", 2);
-}
-
-static result_t com_rd_mem(const char *req)
-{
-	int32_t addr = hex_num(&req);
-
-	if (*req++ != ',') {
-		return RES_DAT("E01", 3);
-	}
-
-	int32_t len = hex_num(&req);
-
-	if (*req != 0 || len == 0) {
-		return RES_DAT("E01", 3);
-	}
-
-	if (len > 10000) {
-		len = 10000;
-	}
-
-	static char buf[10000 * 2 + 1];
-
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	for (int32_t i = 0; i < len; ++i) {
-		uint8_t byte = cpu_peek(addr + i);
-		sprintf(buf + i * 2, "%02x", byte);
-	}
-
-	if (SDL_UnlockMutex(cpu_mutex) < 0) {
-		fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-	}
-
-	return RES_DAT(buf, len * 2);
-}
-
-static result_t com_wr_mem(const char *req)
-{
-	int32_t addr = hex_num(&req);
-
-	if (*req++ != ',') {
-		return RES_DAT("E01", 3);
-	}
-
-	int32_t len = hex_num(&req);
-
-	if (*req++ != ':') {
-		return RES_DAT("E01", 3);
-	}
-
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	int32_t i;
-
-	for (i = 0; i < len; ++i) {
-		int32_t hi = hex_digit(*req++);
-
-		if (hi < 0) {
-			break;
-		}
-
-		int32_t lo = hex_digit(*req++);
-
-		if (lo < 0) {
-			break;
-		}
-
-		cpu_poke(addr + i, (uint8_t)((hi << 4) | lo));
-	}
-
-	if (SDL_UnlockMutex(cpu_mutex) < 0) {
-		fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-	}
-
-	return RES_DAT("OK", 2);
-}
-
-static result_t handle(const char *req)
-{
-	result_t res;
-
-	switch (req[0]) {
-	case '?':
-		res = com_reason();
-		break;
-
-	case 'c':
-		res = com_cont(req + 1);
-		break;
-
-	case 'C':
-		res = com_cont(req + 4);
-		break;
-
-	case 's':
-		res = com_step(req + 1);
-		break;
-
-	case 'S':
-		res = com_step(req + 4);
-		break;
-
-	case 'g':
-		res = com_rd_reg();
-		break;
-
-	case 'G':
-		res = com_wr_reg(req + 1);
-		break;
-
-	case 'm':
-		res = com_rd_mem(req + 1);
-		break;
-
-	case 'M':
-		res = com_wr_mem(req + 1);
-		break;
-
-	default:
-		res = RES_DAT("", 0);
-		break;
-	}
-
-	if (!res.ok || res.n_out > SZ_BUF - 5) {
-		fail("unexpected result");
-	}
-
-	if (res.out == NULL) {
-		return RES_OK;
-	}
-
-	static const uint8_t *hex = (uint8_t *)"0123456789abcdef";
-	static uint8_t buf[SZ_BUF];
-
-	buf[0] = '$';
-	memcpy(buf + 1, res.out, (size_t)res.n_out);
-
-	int32_t sum = 0;
-
-	for (int32_t i = 0; i < res.n_out; ++i) {
-		sum = (sum + res.out[i]) % 256;
-	}
-
-	buf[res.n_out + 1] = '#';
-	buf[res.n_out + 2] = hex[sum / 16];
-	buf[res.n_out + 3] = hex[sum % 16];
-	buf[res.n_out + 4] = 0;
-
-	ver2("resp %s", (char *)buf);
-	return RES_DAT(buf, res.n_out + 4);
-}
-
-static result_t input(uint8_t byte)
-{
-	static int32_t n_buf;
-	static uint8_t buf[SZ_BUF];
-	static int32_t sum;
-	static int32_t check;
-
-	int32_t hex;
-	result_t res;
-
-	ver3("input %c st %d n %d", byte, (int32_t)state, n_buf);
-
-	if (state == STATE_HEAD && byte == 0x03) {
-		stop_cpu();
-		state = STATE_ACK;
-		return RES_DAT("$S05#b8", 7);
-	}
-
-	switch (state) {
-	case STATE_HEAD:
-		if (byte != '$') {
-			err("expected '$'");
-			return RES_ERR;
-		}
-
-		sum = 0;
-		n_buf = 0;
-		state = STATE_DATA;
-		return RES_OK;
-
-	case STATE_DATA:
-		if (n_buf == SZ_BUF - 1) {
-			err("packet too long");
-			return RES_ERR;
-		}
-
-		if (byte == '#') {
-			state = STATE_CHECK_1;
-			return RES_DAT("+", 1);
-		}
-
-		sum = (sum + byte) % 256;
-		buf[n_buf] = byte;
-		++n_buf;
-		return RES_OK;
-
-	case STATE_CHECK_1:
-		hex = hex_digit((char)byte);
-
-		if (hex < 0) {
-			err("malformed checksum (0x%02x)", byte);
-			return RES_ERR;
-		}
-
-		check = hex << 4;
-		state = STATE_CHECK_2;
-		return RES_OK;
-
-	case STATE_CHECK_2:
-		hex = hex_digit((char)byte);
-
-		if (hex < 0) {
-			err("malformed checksum (0x%02x)", byte);
-			return RES_ERR;
-		}
-
-		check |= hex;
-
-		if (sum != check) {
-			err("invalid checksum");
-			return RES_ERR;
-		}
-
-		buf[n_buf] = 0;
-		ver2("pack %s", buf);
-
-		res = handle((char *)buf);
-
-		if (!res.ok) {
-			return RES_ERR;
-		}
-
-		if (res.out == NULL) {
-			state = STATE_HEAD;
-			return RES_OK;
-		}
-
-		state = STATE_ACK;
-		return RES_DAT(res.out, res.n_out);
-
-	case STATE_ACK:
-		if (byte != '+') {
-			err("invalid ACK (0x%02x)", byte);
-			return RES_ERR;
-		}
-
-		state = STATE_HEAD;
-		return RES_OK;
-
-	default:
-		fail("invalid state");
-	}
-
-	// not reached, but Eclipse doesn't know
-	return RES_ERR;
-}
-
-static void con_close(TCPsocket con)
-{
-	if (SDLNet_TCP_DelSocket(set, con) < 0) {
-		fail("SDLNet_TCP_DelSocket() failed: %s", SDLNet_GetError());
-	}
-
-	SDLNet_TCP_Close(con);
-	cont_cpu();
-}
-
-void gdb_loop(void)
-{
-	inf("entering GDB loop");
-	TCPsocket con = NULL;
-
-	while (SDL_AtomicGet(&run) != 0) {
-		int32_t n_act = SDLNet_CheckSockets(set, 100);
-
-		if (n_act < 0) {
-			fail("SDLNet_CheckSockets() failed: %s", SDLNet_GetError());
-		}
-
-		if (SDL_AtomicGet(&lock) == LOCK_BP) {
-			ver2("<- lock bp");
-			stop_cpu();
-			state = STATE_ACK;
-
-			if (con == NULL) {
-				cont_cpu();
-				continue;
-			}
-
-			if (SDLNet_TCP_Send(con, "$S05#b8", 7) != 7) {
-				err("connection error");
-				con_close(con);
-				con = NULL;
-				continue;
-			}
-
-			continue;
-		}
-
-		if (n_act == 0) {
-			continue;
-		}
-
-		if (SDLNet_SocketReady(lis) != 0) {
-			ver("incoming connection");
-
-			if (con != NULL) {
-				ver("closing old");
-				con_close(con);
-			}
-
-			ver("accepting new");
-			con = SDLNet_TCP_Accept(lis);
-
-			if (con == NULL) {
-				fail("SDLNet_TCP_Accept() failed: %s", SDLNet_GetError());
-			}
-
-			if (SDLNet_TCP_AddSocket(set, con) < 0) {
-				fail("SDLNet_AddSocket() failed: %s", SDLNet_GetError());
-			}
-
-			stop_cpu();
-			state = STATE_ACK;
-			continue;
-		}
-
-		if (con == NULL || SDLNet_SocketReady(con) == 0) {
-			continue;
-		}
-
-		ver3("reading");
-		uint8_t byte;
-
-		if (SDLNet_TCP_Recv(con, &byte, 1) < 1) {
-			ver("peer closed");
-			con_close(con);
-			con = NULL;
-			continue;
-		}
-
-		result_t res = input(byte);
-
-		if (!res.ok) {
-			err("invalid packet from GDB");
-			con_close(con);
-			con = NULL;
-			continue;
-		}
-
-		if (res.out == NULL) {
-			continue;
-		}
-
-		if (SDLNet_TCP_Send(con, res.out, res.n_out) != res.n_out) {
-			err("connection error");
-			con_close(con);
-			con = NULL;
-			continue;
-		}
-	}
-
-	if (con != NULL) {
-		con_close(con);
-	}
-
-	inf("leaving GDB loop");
-}
Index: u/kbd.c
===================================================================
--- emu/kbd.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,263 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <all.h>
-
-#define ver(...) _ver(kbd_verbose, 0, __VA_ARGS__)
-#define ver2(...) _ver(kbd_verbose, 1, __VA_ARGS__)
-#define ver3(...) _ver(kbd_verbose, 2, __VA_ARGS__)
-
-int32_t kbd_verbose = 0;
-
-#define BUF_SZ 16
-
-static int32_t buf_hd = 0;
-static int32_t buf_tl = 0;
-static uint8_t buf[BUF_SZ];
-
-static uint8_t reg = 0;
-static bool irq = false;
-
-static void xmit(void)
-{
-	ver2("kbd xmit %d %d", buf_tl, buf_hd);
-
-	if (buf_tl >= buf_hd) {
-		return;
-	}
-
-	reg = buf[buf_tl % BUF_SZ];
-	irq = true;
-	ver2("kbd xmit 0x%02x", reg);
-
-	++buf_tl;
-
-	if (buf_tl >= BUF_SZ) {
-		buf_hd -= BUF_SZ;
-		buf_tl -= BUF_SZ;
-		ver2("kbd adj %d %d", buf_tl, buf_hd);
-	}
-}
-
-static void out(uint8_t c)
-{
-	ver2("kbd out %d %d 0x%02x", buf_tl, buf_hd, c);
-
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	if (buf_hd >= buf_tl + BUF_SZ) {
-		err("keyboard port losing data");
-	}
-	else {
-		buf[buf_hd % BUF_SZ] = c;
-		++buf_hd;
-
-		if (!irq) {
-			xmit();
-		}
-	}
-
-	if (SDL_UnlockMutex(cpu_mutex) < 0) {
-		fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-	}
-}
-
-static void but_on(int32_t sig)
-{
-	out((uint8_t)(0x80 | sig));
-	out(0x01);
-}
-
-static void but_off(int32_t sig)
-{
-	out((uint8_t)(0x80 | sig));
-	out(0x00);
-}
-
-static void key_touch(int32_t sig, int32_t val)
-{
-	out((uint8_t)(0x80 | sig));
-	out(0x01);
-	out((uint8_t)val);
-}
-
-static void key_off(int32_t sig)
-{
-	out((uint8_t)(0x80 | sig));
-	out(0x00);
-}
-
-static void slid(int32_t sig, bool on, int32_t val)
-{
-	out((uint8_t)(0x80 | sig));
-	out(on ? 0x01 : 0x00);
-	out((uint8_t)val);
-}
-
-#if defined NOT_YET
-static void pot(int32_t sig, int32_t val)
-{
-	out((uint8_t)(0x80 | sig));
-	out((uint8_t)val);
-}
-#endif
-
-static void vid_key(SDL_KeyboardEvent *ev, bool dn)
-{
-	if ((ev->keysym.mod & KMOD_SHIFT) != 0 &&
-			ev->keysym.sym >= SDLK_a && ev->keysym.sym <= SDLK_x) {
-		int32_t i = ev->keysym.sym - SDLK_a;
-		ver2("kbd key %d %s", i, dn ? "dn" : "up");
-
-		if (dn) {
-			key_touch(1 + i, 0x7f);
-		}
-		else {
-			key_off(1 + i);
-		}
-
-		return;
-	}
-
-	int32_t sig;
-
-	if (ev->keysym.sym >= SDLK_0 && ev->keysym.sym <= '9') {
-		int32_t i = ev->keysym.sym - SDLK_0;
-		ver2("kbd dat %d %s", i, dn ? "dn" : "up");
-		sig = 60 + i;
-	}
-	else {
-		switch (ev->keysym.sym) {
-		case SDLK_x:
-			ver2("kbd x %s", dn ? "dn" : "up");
-			sig = 70;
-			break;
-
-		case SDLK_e:
-			ver2("kbd e %s", dn ? "dn" : "up");
-			sig = 71;
-			break;
-
-		case SDLK_m:
-			ver2("kbd m %s", dn ? "dn" : "up");
-			sig = 72;
-			break;
-
-		default:
-			return;
-		}
-	}
-
-	if (dn) {
-		but_on(sig);
-	}
-	else {
-		but_off(sig);
-	}
-}
-
-static void lcd_key(SDL_KeyboardEvent *ev, bool dn)
-{
-	if ((ev->keysym.mod & KMOD_CTRL) != 0 &&
-			ev->keysym.sym >= SDLK_a && ev->keysym.sym <= SDLK_n) {
-		int32_t i = ev->keysym.sym - SDLK_a;
-		ver2("kbd lcd %d %s", i, dn ? "dn" : "up");
-
-		if (dn) {
-			but_on(39 + i);
-		}
-		else {
-			but_off(39 + i);
-		}
-
-		return;
-	}
-
-	if (ev->keysym.sym >= SDLK_a && ev->keysym.sym <= SDLK_n) {
-		static int32_t lev[14] = {
-			64, 0, 0, 0, 0, 64, 64, 64, 64, 0, 0, 0, 64, 0
-		};
-
-		int32_t i = ev->keysym.sym - SDLK_a;
-		int32_t val = lev[i];
-
-		if (!dn) {
-			if ((ev->keysym.mod & KMOD_SHIFT) != 0) {
-				val = val > 10 ? val - 10 : 0;
-			}
-			else {
-				val = val < 117 ? val + 10 : 127;
-			}
-		}
-
-		ver2("kbd sli %d %s %d", i, dn ? "dn" : "up", val);
-		slid(25 + i, dn, val);
-
-		lev[i] = val;
-		return;
-	}
-}
-
-void kbd_key(SDL_KeyboardEvent *ev, bool vid, bool dn)
-{
-	if (vid) {
-		vid_key(ev, dn);
-	}
-	else {
-		lcd_key(ev, dn);
-	}
-}
-
-void kbd_init(void)
-{
-	ver("kbd init");
-}
-
-void kbd_quit(void)
-{
-	ver("kbd quit");
-}
-
-bool kbd_exec(void)
-{
-	ver3("kbd exec");
-	return irq;
-}
-
-uint32_t kbd_read(uint32_t off, int32_t sz)
-{
-	ver2("kbd rd %u:%d", off, sz * 8);
-
-	if (sz != 1 || off > 0) {
-		fail("invalid kbd rd %u:%d", off, sz * 8);
-	}
-
-	irq = false;
-	uint32_t res = reg;
-
-	xmit();
-
-	return res;
-}
-
-void kbd_write(uint32_t off, int32_t sz, uint32_t val)
-{
-	ver2("kbd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
-	fail("invalid kbd wr %u:%d", off, sz * 8);
-}
Index: u/lcd.c
===================================================================
--- emu/lcd.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,413 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <all.h>
-
-#define ver(...) _ver(lcd_verbose, 0, __VA_ARGS__)
-#define ver2(...) _ver(lcd_verbose, 1, __VA_ARGS__)
-#define ver3(...) _ver(lcd_verbose, 2, __VA_ARGS__)
-
-int32_t lcd_verbose = 0;
-
-#define WIN_W (1615 / 2)
-#define WIN_H (304 / 2)
-
-#define GFX_BGR 0x00000000
-#define GFX_FGR 0xFFFFFFFF
-
-#define TXT_BGR 0x000000FF
-#define TXT_FGR ((SDL_Color){ .r = 255, .b = 255, .g = 255, .a = 255 })
-
-#define REG_ARG 0
-#define REG_COM 1
-
-#define COM_NONE	0x00
-#define	COM_MWRITE	0x42
-#define	COM_MREAD	0x43
-#define	COM_CRSWR	0x46
-#define	COM_CRSMRT	0x4C
-#define	COM_CRSMUP	0x4E
-#define	COM_CRSMDN	0x4F
-#define	COM_DSPOFF	0x58
-#define	COM_DSPON	0x59
-
-#define TXT_W 85
-#define TXT_H 8
-
-#define GFX_W 85
-#define GFX_H 64
-#define GFX_PIX 6
-
-#define BASE_TXT 0x0000
-#define BASE_GFX 0x2000
-
-#define DIR_UP -85
-#define DIR_DOWN 85
-#define DIR_RIGHT 1
-
-static uint8_t mem_txt[TXT_H * TXT_W];
-static uint8_t mem_gfx[GFX_H * GFX_W];
-
-static SDL_Window *win;
-uint32_t lcd_win;
-
-static SDL_Renderer *ren;
-static SDL_atomic_t frame;
-static SDL_atomic_t ena;
-
-static TTF_Font *fon;
-static int32_t fon_w, fon_h;
-
-static int32_t txt_w, txt_h;
-static SDL_Surface *txt;
-static SDL_Texture *gfx;
-
-static int32_t com;
-static int32_t n_arg;
-static int32_t cur = BASE_TXT;
-static int32_t dir = DIR_RIGHT;
-
-void lcd_sdl(void)
-{
-	ver3("lcd_sdl()");
-
-	static int32_t last = 0;
-	int32_t now = SDL_AtomicGet(&frame);
-
-	if (last == now) {
-		ver3("no update");
-		return;
-	}
-
-	last = now;
-
-	if (SDL_FillRect(txt, NULL, TXT_BGR) < 0) {
-		fail("SDL_FillRect() failed: %s", SDL_GetError());
-	}
-
-	if (SDL_AtomicGet(&ena) == 0) {
-		SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, txt);
-
-		if (tex == NULL) {
-			fail("SDL_CreateTextureFromSurface() failed: %s", SDL_GetError());
-		}
-
-		if (SDL_RenderCopy(ren, tex, NULL, NULL) < 0) {
-			fail("SDL_RenderCopy() failed: %s", SDL_GetError());
-		}
-
-		SDL_DestroyTexture(tex);
-		SDL_RenderPresent(ren);
-		return;
-	}
-
-	for (int32_t y = 0; y < TXT_H; ++y) {
-		char line[TXT_W + 1];
-		line[TXT_W] = 0;
-
-		if (SDL_LockMutex(cpu_mutex) < 0) {
-			fail("SDL_LockMutex() failed: %s", SDL_GetError());
-		}
-
-		memcpy(line, mem_txt + y * TXT_W, TXT_W);
-
-		if (SDL_UnlockMutex(cpu_mutex) < 0) {
-			fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-		}
-
-		for (int32_t x = 0; x < TXT_W; ++x) {
-			if (line[x] == 0x00) {
-				line[x] = ' ';
-			}
-			else if (line[x] == 0x7e) {
-				line[x] = (char) 0xbb;
-			}
-			else if (line[x] == 0x7f) {
-				line[x] = (char) 0xab;
-			}
-		}
-
-		SDL_Surface *lin = TTF_RenderText_Blended(fon, line, TXT_FGR);
-
-		if (lin == NULL) {
-			fail("TTF_RenderText_Blended() failed: %s", TTF_GetError());
-		}
-
-		if (SDL_BlitSurface(lin, NULL, txt, &(SDL_Rect){
-			.x = 0,
-			.y = y * fon_h,
-			.w = TXT_W * fon_w,
-			.h = fon_h
-		})) {
-			fail("SDL_BlitSurface() failed: %s", SDL_GetError());
-		}
-
-		SDL_FreeSurface(lin);
-	}
-
-	SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, txt);
-
-	if (tex == NULL) {
-		fail("SDL_CreateTextureFromSurface() failed: %s", SDL_GetError());
-	}
-
-	if (SDL_RenderCopy(ren, tex, NULL, NULL) < 0) {
-		fail("SDL_RenderCopy() failed: %s", SDL_GetError());
-	}
-
-	SDL_DestroyTexture(tex);
-
-	void *buf;
-	int32_t pitch;
-
-	if (SDL_LockTexture(gfx, NULL, &buf, &pitch) < 0) {
-		fail("SDL_LockTexture() failed: %s", SDL_GetError());
-	}
-
-	uint32_t *pix = buf;
-
-	for (int32_t y = 0; y < GFX_H; ++y) {
-		for (int32_t x = 0; x < GFX_W; ++x) {
-			uint8_t b = mem_gfx[y * GFX_W + x];
-
-			for (int32_t p = 0; p < GFX_PIX; ++p) {
-				bool set = (b & (1 << (7 - p))) != 0;
-				*pix++ = set ? GFX_FGR : GFX_BGR;
-			}
-		}
-
-		pix += pitch / 4 - GFX_W * GFX_PIX;
-	}
-
-	SDL_UnlockTexture(gfx);
-
-	if (SDL_RenderCopy(ren, gfx, NULL, NULL) < 0) {
-		fail("SDL_RenderCopy() failed: %s", SDL_GetError());
-	}
-
-	SDL_RenderPresent(ren);
-}
-
-void lcd_init(void)
-{
-	ver("lcd init");
-
-	win = SDL_CreateWindow("LCD", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
-			WIN_W, WIN_H, 0);
-
-	if (win == NULL) {
-		fail("SDL_CreateWindow() failed: %s", SDL_GetError());
-	}
-
-	lcd_win = SDL_GetWindowID(win);
-
-	if (lcd_win == 0) {
-		fail("SDL_GetWindowID() failed: %s", SDL_GetError());
-	}
-
-	ren = SDL_CreateRenderer(win, -1, 0);
-
-	if (ren == NULL) {
-		fail("SDL_CreateRenderer() failed: %s", SDL_GetError());
-	}
-
-	gfx = SDL_CreateTexture(ren, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING,
-			GFX_W * GFX_PIX, GFX_H);
-
-	if (gfx == NULL) {
-		fail("SDL_CreateTexture() failed: %s", SDL_GetError());
-	}
-
-	if (SDL_SetTextureBlendMode(gfx, SDL_BLENDMODE_BLEND) < 0) {
-		fail("SDL_SetTextureBlendMode() failed: %s", SDL_GetError());
-	}
-
-	SDL_RWops *ops = SDL_RWFromFile(font, "rb");
-
-	if (ops == NULL) {
-		fail("error while opening font file %s: %s", font, SDL_GetError());
-	}
-
-	fon = TTF_OpenFontRW(ops, 1, 32);
-
-	if (fon == NULL) {
-		fail("error while loading font file %s: %s", font, TTF_GetError());
-	}
-
-	fon_h = TTF_FontLineSkip(fon);
-
-	if (TTF_GlyphMetrics(fon, 'X', NULL, NULL, NULL, NULL, &fon_w) < 0) {
-		fail("error while measuring font width: %s", TTF_GetError());
-	}
-
-	txt_w = TXT_W * fon_w;
-	txt_h = TXT_H * fon_h;
-
-	txt = SDL_CreateRGBSurfaceWithFormat(0, txt_w, txt_h, 32, SDL_PIXELFORMAT_RGBA8888);
-
-	if (txt == NULL) {
-		fail("SDL_CreateRGBSurface() failed: %s", SDL_GetError());
-	}
-
-	for (int32_t i = 0; i < TXT_W * TXT_H; ++i) {
-		mem_txt[i] = ' ';
-	}
-}
-
-void lcd_quit(void)
-{
-	ver("lcd quit");
-
-	SDL_FreeSurface(txt);
-	TTF_CloseFont(fon);
-
-	SDL_DestroyTexture(gfx);
-
-	SDL_DestroyRenderer(ren);
-	SDL_DestroyWindow(win);
-}
-
-bool lcd_exec(void)
-{
-	ver3("lcd exec");
-	return false;
-}
-
-uint32_t lcd_read(uint32_t off, int32_t sz)
-{
-	ver2("lcd rd %u:%d", off, sz * 8);
-
-	if (sz != 1 || off != 1) {
-		fail("invalid lcd rd %u:%d", off, sz * 8);
-	}
-
-	switch (com) {
-	case COM_MREAD:
-		if (cur >= BASE_TXT && cur < BASE_TXT + TXT_W * TXT_H) {
-			return mem_txt[cur - BASE_TXT];
-		}
-
-		if (cur >= BASE_GFX && cur < BASE_GFX + GFX_W * GFX_H) {
-			return mem_gfx[cur - BASE_GFX];
-		}
-
-		return 0x00;
-
-	default:
-		return 0x00;
-	}
-}
-
-static void proc_arg(int32_t val)
-{
-	switch (com) {
-	case COM_MWRITE:
-		if (cur >= BASE_TXT && cur < BASE_TXT + TXT_W * TXT_H) {
-			mem_txt[cur - BASE_TXT] = (uint8_t)val;
-		}
-		else if (cur >= BASE_GFX && cur < BASE_GFX + GFX_W * GFX_H) {
-			mem_gfx[cur - BASE_GFX] = (uint8_t)val;
-		}
-
-		cur += dir;
-		SDL_AtomicAdd(&frame, 1);
-		break;
-
-	case COM_CRSWR:
-		if (n_arg == 0) {
-			cur = val;
-		}
-		else if (n_arg == 1) {
-			cur |= val << 8;
-
-			if (cur < BASE_TXT ||
-					(cur >= BASE_TXT + TXT_W * TXT_H && cur < BASE_GFX) ||
-					cur >= BASE_GFX + GFX_W * GFX_H) {
-				fail("invalid address 0x%04x", cur);
-			}
-		}
-
-		break;
-
-	default:
-		break;
-	}
-}
-
-static void proc_com(int32_t val)
-{
-	switch (val) {
-	case COM_CRSWR:
-	case COM_MREAD:
-	case COM_MWRITE:
-		com = val;
-		break;
-
-	case COM_CRSMRT:
-		dir = DIR_RIGHT;
-		com = COM_NONE;
-		break;
-
-	case COM_CRSMUP:
-		dir = DIR_UP;
-		com = COM_NONE;
-		break;
-
-	case COM_CRSMDN:
-		dir = DIR_DOWN;
-		com = COM_NONE;
-		break;
-
-	case COM_DSPOFF:
-		SDL_AtomicSet(&ena, 0);
-		com = COM_NONE;
-		break;
-
-	case COM_DSPON:
-		SDL_AtomicSet(&ena, 1);
-		com = COM_NONE;
-		break;
-
-	default:
-		com = COM_NONE;
-		break;
-	}
-}
-
-void lcd_write(uint32_t off, int32_t sz, uint32_t val)
-{
-	ver2("lcd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
-
-	if (sz != 1 || off > 1) {
-		fail("invalid lcd wr %u:%d", off, sz * 8);
-	}
-
-	switch (off) {
-	case REG_ARG:
-		proc_arg((int32_t)val);
-		++n_arg;
-		break;
-
-	case REG_COM:
-		proc_com((int32_t)val);
-		n_arg = 0;
-		break;
-
-	default:
-		break;
-	}
-}
Index: u/led.c
===================================================================
--- emu/led.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,51 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <all.h>
-
-#define ver(...) _ver(led_verbose, 0, __VA_ARGS__)
-#define ver2(...) _ver(led_verbose, 1, __VA_ARGS__)
-#define ver3(...) _ver(led_verbose, 2, __VA_ARGS__)
-
-int32_t led_verbose = 0;
-
-void led_init(void)
-{
-	ver("led init");
-}
-
-void led_quit(void)
-{
-	ver("led quit");
-}
-
-bool led_exec(void)
-{
-	ver3("led exec");
-	return false;
-}
-
-uint32_t led_read(uint32_t off, int32_t sz)
-{
-	ver2("led rd %u:%d", off, sz * 8);
-	return 0;
-}
-
-void led_write(uint32_t off, int32_t sz, uint32_t val)
-{
-	ver2("led wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
-}
Index: u/main.c
===================================================================
--- emu/main.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,213 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <all.h>
-
-typedef struct {
-	const char *name;
-	int32_t *flag;
-} verb_flag_t;
-
-static verb_flag_t verb_flags[] = {
-	{ "sdl", &sdl_verbose },
-	{ "gdb", &gdb_verbose },
-	{ "cpu", &cpu_verbose },
-	{ "fpu", &fpu_verbose },
-	{ "vid", &vid_verbose },
-	{ "tim", &tim_verbose },
-	{ "lcd", &lcd_verbose },
-	{ "ser", &ser_verbose },
-	{ "mid", &mid_verbose },
-	{ "fdd", &fdd_verbose },
-	{ "snd", &snd_verbose },
-	{ "led", &led_verbose },
-	{ "kbd", &kbd_verbose }
-};
-
-const char *bios = "bios.abs";
-const char *disk = "buchla.disk";
-const char *font = "vera.ttf";
-
-uint32_t mid_port = 0;
-
-SDL_atomic_t run;
-
-static void usage(FILE *fh)
-{
-	fprintf(fh, "usage: buchla [-h] [-v comp [-v comp [...]]] [-b bios] [-d disk] [-f font] [-m port]\n");
-	fprintf(fh, "with\n");
-	fprintf(fh, "  comp - one of: ");
-
-	for (int32_t i = 0; i < ARRAY_COUNT(verb_flags); ++i) {
-		fprintf(fh, "%s, ", verb_flags[i].name);
-	}
-
-	fprintf(fh, "all\n");
-	fprintf(fh, "  bios - BIOS ROM file (default: bios.abs)\n");
-	fprintf(fh, "  disk - disk image file (default: buchla.disk)\n");
-	fprintf(fh, "  font - console and LCD font (default: vera.ttf)\n");
-	fprintf(fh, "  port - number of the desired MIDI port (default: 0)\n");
-	fprintf(fh, "         \"list\" instead of a port number lists available ports\n");
-}
-
-static void parse_args(int32_t argc, char *argv[])
-{
-	for (int32_t i = 0; i < argc; ++i) {
-		if (strcmp(argv[i], "-h") == 0) {
-			usage(stdout);
-			exit(0);
-		}
-
-		if (strcmp(argv[i], "-b") == 0) {
-			if (++i == argc) {
-				usage(stderr);
-				fprintf(stderr, "missing argument to -b\n");
-				exit(1);
-			}
-
-			bios = argv[i];
-			continue;
-		}
-
-		if (strcmp(argv[i], "-d") == 0) {
-			if (++i == argc) {
-				usage(stderr);
-				fprintf(stderr, "missing argument to -d\n");
-				exit(1);
-			}
-
-			disk = argv[i];
-			continue;
-		}
-
-		if (strcmp(argv[i], "-f") == 0) {
-			if (++i == argc) {
-				usage(stderr);
-				fprintf(stderr, "missing argument to -f\n");
-				exit(1);
-			}
-
-			font = argv[i];
-			continue;
-		}
-
-		if (strcmp(argv[i], "-v") == 0) {
-			if (++i == argc) {
-				usage(stderr);
-				fprintf(stderr, "missing argument to -v\n");
-				exit(1);
-			}
-
-			int32_t k;
-
-			if (strcmp(argv[i], "all") == 0) {
-				for (k = 0; k < ARRAY_COUNT(verb_flags); ++k) {
-					++*verb_flags[k].flag;
-				}
-
-				continue;
-			}
-
-			for (k = 0; k < ARRAY_COUNT(verb_flags); ++k) {
-				if (strcmp(argv[i], verb_flags[k].name) == 0) {
-					++*verb_flags[k].flag;
-					break;
-				}
-			}
-
-			if (k == ARRAY_COUNT(verb_flags)) {
-				usage(stderr);
-				fprintf(stderr, "invalid argument to -v: %s\n", argv[i]);
-				exit(1);
-			}
-
-			continue;
-		}
-
-		if (strcmp(argv[i], "-m") == 0) {
-			if (++i == argc) {
-				usage(stderr);
-				fprintf(stderr, "missing argument to -m\n");
-				exit(1);
-			}
-
-			if (strcmp(argv[i], "list") == 0) {
-				mid_list();
-				exit(0);
-			}
-
-			char *end;
-			int64_t tmp = strtol(argv[i], &end, 10);
-
-			if (*end != 0 || tmp < 0 || tmp > 15) {
-				usage(stderr);
-				fprintf(stderr, "invalid argument to -m: %s\n", argv[i]);
-				exit(1);
-			}
-
-			mid_port = (uint32_t)tmp;
-			continue;
-		}
-	}
-}
-
-static int32_t cpu_thread(void *data)
-{
-	(void)data;
-
-	cpu_loop();
-	return 0;
-}
-
-static int32_t gdb_thread(void *data)
-{
-	(void)data;
-
-	gdb_loop();
-	return 0;
-}
-
-int32_t main(int32_t argc, char *argv[])
-{
-	parse_args(argc, argv);
-	sdl_init();
-	gdb_init();
-	cpu_init();
-
-	SDL_AtomicSet(&run, 1);
-	SDL_Thread *thr_cpu = SDL_CreateThread(cpu_thread, "cpu", NULL);
-
-	if (thr_cpu == NULL) {
-		fail("SDL_CreateThread() failed: %s", SDL_GetError());
-	}
-
-	SDL_Thread *thr_gdb = SDL_CreateThread(gdb_thread, "gdb", NULL);
-
-	if (thr_gdb == NULL) {
-		fail("SDL_CreateThread() failed: %s", SDL_GetError());
-	}
-
-	sdl_loop();
-
-	SDL_WaitThread(thr_cpu, NULL);
-	SDL_WaitThread(thr_gdb, NULL);
-
-	cpu_quit();
-	gdb_quit();
-	sdl_quit();
-	return 0;
-}
Index: u/mid.c
===================================================================
--- emu/mid.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,318 +1,0 @@
-/*
- *  Copyright (C) 2017-2018 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <all.h>
-
-#define ver(...) _ver(mid_verbose, 0, __VA_ARGS__)
-#define ver2(...) _ver(mid_verbose, 1, __VA_ARGS__)
-#define ver3(...) _ver(mid_verbose, 2, __VA_ARGS__)
-
-int32_t mid_verbose = 0;
-
-#define REG_IER_ISR 0
-#define REG_CFR_SR  1
-#define REG_CDR_TBR 2
-#define REG_TDR_RDR 3
-
-#define BUF_SZ 256
-
-typedef struct {
-	int32_t buf_hd;
-	int32_t buf_tl;
-	uint8_t buf[BUF_SZ];
-	bool irq_r;
-	bool irq_t;
-	bool rdr_ok;
-	uint8_t rdr;
-} state_t;
-
-static state_t state[] = {
-	{ .buf_hd = 0, .buf_tl = 0, .irq_r = false, .irq_t = false, .rdr_ok = false, .rdr = 0x00 },
-	{ .buf_hd = 0, .buf_tl = 0, .irq_r = false, .irq_t = false, .rdr_ok = false, .rdr = 0x00 }
-};
-
-static struct RtMidiWrapper *mid_in = NULL;
-
-static void xmit(int32_t un)
-{
-	int32_t i = state[un].buf_tl;
-	ver2("mid xmit %d %d", i, state[un].buf_hd);
-
-	if (i >= state[un].buf_hd) {
-		return;
-	}
-
-	uint8_t byte = state[un].buf[i % BUF_SZ];
-	ver2("mid xmit 0x%02x", byte);
-
-	state[un].rdr = byte;
-	state[un].rdr_ok = true;
-	state[un].irq_r = true;
-
-	state[un].buf_tl = i + 1;
-
-	if (state[un].buf_tl >= BUF_SZ) {
-		state[un].buf_hd -= BUF_SZ;
-		state[un].buf_tl -= BUF_SZ;
-		ver2("mid adj %d %d", state[un].buf_tl, state[un].buf_hd);
-	}
-}
-
-static void out(int32_t un, uint8_t c)
-{
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	int32_t i = state[un].buf_hd;
-	ver2("mid out %d %d 0x%02x", state[un].buf_tl, i, c);
-
-	if (i >= state[un].buf_tl + BUF_SZ) {
-		err("midi port %d losing data", un);
-		return;
-	}
-
-	state[un].buf[i % BUF_SZ] = c;
-	state[un].buf_hd = i + 1;
-
-	if (!state[un].irq_r && !state[un].rdr_ok) {
-		xmit(un);
-	}
-
-	if (SDL_UnlockMutex(cpu_mutex) < 0) {
-		fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-	}
-}
-
-static void callback(double time, const uint8_t *midi, void *data)
-{
-	(void)data;
-
-	// XXX - remove length calculation once RtMidi passes the length
-
-	int32_t len;
-
-	switch (midi[0] & 0xf0) {
-	case 0x80: // note on
-	case 0x90: // note off
-	case 0xa0: // polyphonic key pressure
-	case 0xb0: // control change
-	case 0xe0: // pitch bend change
-		len = 3;
-		break;
-
-	case 0xc0: // program change
-	case 0xd0: // channel pressure
-		len = 2;
-		break;
-
-	case 0xf0:
-		switch (midi[0]) {
-		case 0xf0: // system exclusive
-		case 0xf4: // undefined
-		case 0xf5: // undefined
-		case 0xf7: // end of exclusive
-		case 0xf9: // undefined
-		case 0xfd: // undefined
-			len = -1;
-			break;
-
-		case 0xf1: // MIDI time code quarter frame
-		case 0xf3: // song select
-			len = 2;
-			break;
-
-		case 0xf2: // song position pointer
-			len = 3;
-			break;
-
-		case 0xf6: // tune request
-		case 0xf8: // timing clock
-		case 0xfa: // start
-		case 0xfb: // continue
-		case 0xfc: // stop
-		case 0xfe: // active sensing
-		case 0xff: // reset
-			len = 1;
-			break;
-		}
-
-		break;
-
-	default:
-		len = 0;
-		break;
-	}
-
-	ver2("time %f, len %d", time, len);
-
-	for (int32_t i = 0; i < len; ++i) {
-		ver2("midi[%d] 0x%02x", i, midi[i]);
-		out(0, midi[i]);
-	}
-}
-
-void mid_init(void)
-{
-	ver("mid init");
-
-	mid_in = rtmidi_in_create_default();
-	mid_in->data = NULL; // XXX - remove initialization once it's added to RtMidi
-
-	if (!mid_in->ok) {
-		fail("rtmidi_in_create_default() failed: %s", mid_in->msg);
-	}
-
-	uint32_t n_ports = rtmidi_get_port_count(mid_in);
-
-	if (n_ports == 0) {
-		inf("no MIDI ports\n");
-		rtmidi_in_free(mid_in);
-		mid_in = NULL;
-		return;
-	}
-
-	if (mid_port >= n_ports) {
-		fail("invalid MIDI port %u selected (%u available)", mid_port, n_ports);
-	}
-
-	const char *name = rtmidi_get_port_name(mid_in, mid_port);
-	rtmidi_open_port(mid_in, mid_port, name);
-
-	if (!mid_in->ok) {
-		fail("error while opening MIDI port %u (%s): %s", mid_port, name, mid_in->msg);
-	}
-
-	inf("using MIDI port %u (%s)", mid_port, name);
-	free((char *)name);
-
-	rtmidi_in_set_callback(mid_in, callback, mid_in->data);
-
-	if (!mid_in->ok) {
-		fail("rtmidi_in_set_callback() failed: %s", mid_in->msg);
-	}
-}
-
-void mid_quit(void)
-{
-	ver("mid quit");
-
-	if (mid_in == NULL) {
-		return;
-	}
-
-	rtmidi_close_port(mid_in);
-	rtmidi_in_free(mid_in);
-}
-
-bool mid_exec(void)
-{
-	ver3("mid exec");
-	return state[0].irq_r || state[0].irq_t || state[1].irq_r || state[1].irq_t;
-}
-
-uint32_t mid_read(uint32_t off, int32_t sz)
-{
-	ver2("mid rd %u:%d", off, sz * 8);
-
-	if (sz != 1 || off > 7) {
-		fail("invalid mid rd %u:%d", off, sz * 8);
-	}
-
-	int32_t rg = (int32_t)(off % 4);
-	int32_t un = (int32_t)(off / 4);
-
-	uint32_t rv;
-
-	switch (rg) {
-	case REG_IER_ISR:
-		rv = (uint32_t)(0xc0 | (state[un].rdr_ok ? 0x01 : 0x00));
-		state[un].irq_r = false;
-		state[un].irq_t = false;
-		ver2("ISR[%d] 0x%02x", un, rv);
-		break;
-
-	case REG_TDR_RDR:
-		rv = state[un].rdr;
-		state[un].rdr_ok = false;
-		ver2("RDR[%d] 0x%02x", un, rv);
-		break;
-
-	default:
-		rv = 0x00;
-		break;
-	}
-
-	if (!state[un].irq_r && !state[un].rdr_ok) {
-		xmit(un);
-	}
-
-	return rv;
-}
-
-void mid_write(uint32_t off, int32_t sz, uint32_t val)
-{
-	ver2("mid wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
-
-	if (sz != 1 || off > 7) {
-		fail("invalid mid wr %u:%d", off, sz * 8);
-	}
-
-	int32_t rg = (int32_t)(off % 4);
-	int32_t un = (int32_t)(off / 4);
-
-	switch (rg) {
-	case REG_CFR_SR:
-		ver2("CFR[%d] 0x%02x", un, val);
-
-		if (un == 1) {
-			fdd_set_side((int32_t)val & 0x01);
-		}
-		else {
-			fdd_set_sel((int32_t)val & 0x01);
-		}
-
-		break;
-
-	default:
-		break;
-	}
-}
-
-void mid_list(void)
-{
-	mid_in = rtmidi_in_create_default();
-	mid_in->data = NULL; // XXX - remove initialization once it's added to RtMidi
-
-	if (!mid_in->ok) {
-		fprintf(stderr, "rtmidi_in_create_default() failed: %s\n", mid_in->msg);
-		return;
-	}
-
-	uint32_t n_ports = rtmidi_get_port_count(mid_in);
-
-	if (n_ports == 0) {
-		fprintf(stdout, "no available MIDI ports\n");
-	}
-	else {
-		for (uint32_t i = 0; i < n_ports; i++) {
-			fprintf(stdout, "port %u: %s\n", i, rtmidi_get_port_name(mid_in, i));
-		}
-	}
-
-	rtmidi_in_free(mid_in);
-}
Index: u/mkdisk.c
===================================================================
--- emu/mkdisk.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,273 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sys/types.h>
-
-#define DISK_FILE_NAME "buchla.disk"
-#define MIDAS_FILE_NAME "midas.abs"
-
-#define N_CYL 80
-#define N_SID 2
-#define N_SEC 9
-#define SZ_SEC 512
-
-#define N_SEC_CLU 2
-#define SZ_CLU (SZ_SEC * N_SEC_CLU)
-
-#define N_BOOT_SEC 1
-#define N_FAT_SEC 3
-#define N_ROOT_SEC 7
-
-#define N_FAT 2
-#define SZ_DIR_ENT 32
-
-#define ROOT_SEC (N_BOOT_SEC + N_FAT_SEC * N_FAT)
-#define N_META_SEC (ROOT_SEC + N_ROOT_SEC)
-
-static uint8_t midas[1024 * 1024];
-static int32_t sz_midas;
-
-static uint8_t disk[N_CYL * N_SID * N_SEC][SZ_SEC];
-
-static int32_t put_sec_8(int32_t sec, int32_t off, int32_t val)
-{
-	disk[sec][off] = (uint8_t)val;
-	return off + 1;
-}
-
-static int32_t put_sec_16(int32_t sec, int32_t off, int32_t val)
-{
-	disk[sec][off + 0] = (uint8_t)(val >> 0);
-	disk[sec][off + 1] = (uint8_t)(val >> 8);
-	return off + 2;
-}
-
-static int32_t put_sec_32(int32_t sec, int32_t off, int32_t val)
-{
-	off = put_sec_16(sec, off, val & 65535);
-	off = put_sec_16(sec, off, val >> 16);
-	return off;
-}
-
-static int32_t put_sec_str(int32_t sec, int32_t off, const char *str, int32_t len)
-{
-	int32_t i;
-
-	for (i = 0;  str[i] != 0 && i < len; ++i) {
-		disk[sec][off + i] = (uint8_t)str[i];
-	}
-
-	while (i < len) {
-		disk[sec][off + i] = ' ';
-		++i;
-	}
-
-	return off + i;
-}
-
-static int32_t put_fat_12(int32_t sec, int32_t ent, int32_t val)
-{
-	uint8_t *fat = disk[sec];
-
-	int32_t off = ent / 2 * 3;
-	int32_t bit = (ent % 2) * 12;
-
-	int32_t tmp = 0;
-
-	tmp |= fat[off + 0] <<  0;
-	tmp |= fat[off + 1] <<  8;
-	tmp |= fat[off + 2] << 16;
-
-	tmp = (tmp & ~(0xfff << bit)) | (val << bit);
-
-	fat[off + 0] = (uint8_t)(tmp >>  0);
-	fat[off + 1] = (uint8_t)(tmp >>  8);
-	fat[off + 2] = (uint8_t)(tmp >> 16);
-
-	return ent + 1;
-}
-
-static void init_boot_sector(void)
-{
-	int32_t off = 0;
-
-	// magic number
-	off = put_sec_8(0, off, 0xe9);
-	off = put_sec_8(0, off, 0x00);
-
-	// OEM
-	off = put_sec_str(0, off, "EMUL", 6);
-
-	// serial number
-	off = put_sec_8(0, off, 0x01);
-	off = put_sec_8(0, off, 0x02);
-	off = put_sec_8(0, off, 0x03);
-
-	// bytes per sector
-	off = put_sec_16(0, off, SZ_SEC);
-
-	// sectors per cluster
-	off = put_sec_8(0, off, N_SEC_CLU);
-
-	// number of reserved sectors
-	off = put_sec_16(0, off, N_BOOT_SEC);
-
-	// number of FATs
-	off = put_sec_8(0, off, N_FAT);
-
-	// maximum number of root directory entries
-	off = put_sec_16(0, off, N_ROOT_SEC * SZ_SEC / SZ_DIR_ENT);
-
-	// total number of sectors
-	off = put_sec_16(0, off, N_CYL * N_SID * N_SEC);
-
-	// media descriptor (floppy disk, 720k)
-	off = put_sec_8(0, off, 0xf9);
-
-	// sectors per FAT (9 * 512 / 3 * 2 = 3072)
-	off = put_sec_16(0, off, N_FAT_SEC);
-
-	// sectors per track
-	off = put_sec_16(0, off, N_SEC);
-
-	// number of sides
-	off = put_sec_16(0, off, N_SID);
-
-	// number of hidden sectors
-	off = put_sec_16(0, off, 0);
-
-	put_sec_8(0, SZ_SEC - 2, 0x55);
-	put_sec_8(0, SZ_SEC - 1, 0xaa);
-}
-
-static void init_fat(int32_t sec)
-{
-	int32_t ent = 0;
-
-	ent = put_fat_12(sec, ent, 0xff9);
-	ent = put_fat_12(sec, ent, 0xfff);
-
-	int32_t n_clu = (sz_midas + SZ_CLU - 1) / SZ_CLU;
-
-	for (int32_t i = 0; i < n_clu - 1; ++i) {
-		ent = put_fat_12(sec, ent, ent + 1);
-	}
-
-	put_fat_12(sec, ent, 0xfff);
-}
-
-static void init_midas(void)
-{
-	int32_t off = 0;
-
-	// file name
-	off = put_sec_str(ROOT_SEC, off, "MIDAS", 8);
-
-	// extension
-	off = put_sec_str(ROOT_SEC, off, "ABS", 3);
-
-	// file attributes (0x20 = archive)
-	off = put_sec_8(ROOT_SEC, off, 0x20);
-
-	// unused
-	for (int32_t i = 0; i < 10; ++i) {
-		off = put_sec_8(ROOT_SEC, off, 0x00);
-	}
-
-	// last modified time (12:34:56)
-	off = put_sec_16(ROOT_SEC, off, (12 << 11) | (34 << 5) | (56 / 2));
-
-	// last modified date (1988-06-20)
-	off = put_sec_16(ROOT_SEC, off, (8 << 9) | (6 << 5) | 20);
-
-	// start cluster
-	off = put_sec_16(ROOT_SEC, off, 2);
-
-	// file size
-	off = put_sec_32(ROOT_SEC, off, sz_midas);
-
-	int32_t n_sec = (sz_midas + SZ_SEC - 1) / SZ_SEC;
-	memcpy(disk[N_META_SEC], midas, (size_t)n_sec * SZ_SEC);
-}
-
-static void write_disk(void)
-{
-	FILE *fh = fopen(DISK_FILE_NAME, "wb");
-
-	if (fh == NULL || fwrite(disk, sizeof disk, 1, fh) != 1) {
-		fprintf(stderr, "error while writing disk file " DISK_FILE_NAME "\n");
-		exit(1);
-	}
-
-	fclose(fh);
-}
-
-static void load_midas(void)
-{
-	FILE *fh = fopen(MIDAS_FILE_NAME, "rb");
-
-	if (fh == NULL) {
-		fprintf(stderr, "error while opening MIDAS file " MIDAS_FILE_NAME "\n");
-		exit(1);
-	}
-
-	if (fseek(fh, 0, SEEK_END) < 0) {
-		fprintf(stderr, "error while seeking in MIDAS file " MIDAS_FILE_NAME "\n");
-		exit(1);
-	}
-
-	ssize_t len = ftell(fh);
-
-	if (len < 0) {
-		fprintf(stderr, "error while determining size of MIDAS file " MIDAS_FILE_NAME "\n");
-		exit(1);
-	}
-
-	sz_midas = (int32_t)len;
-	rewind(fh);
-
-	if (fread(midas, (size_t)sz_midas, 1, fh) != 1) {
-		fprintf(stderr, "error while reading MIDAS file " MIDAS_FILE_NAME "\n");
-		exit(1);
-	}
-
-	fclose(fh);
-}
-
-int32_t main(int32_t argc, char *argv[])
-{
-	(void)argc;
-	(void)argv;
-
-	load_midas();
-	init_boot_sector();
-
-	for (int32_t i = 0; i < N_FAT; ++i) {
-		init_fat(N_BOOT_SEC + i * N_FAT_SEC);
-	}
-
-	init_midas();
-	write_disk();
-	return 0;
-}
Index: u/sdl.c
===================================================================
--- emu/sdl.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,201 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <all.h>
-
-int32_t sdl_verbose = 0;
-
-#define ver(...) _ver(sdl_verbose, 0, __VA_ARGS__)
-#define ver2(...) _ver(sdl_verbose, 1, __VA_ARGS__)
-#define ver3(...) _ver(sdl_verbose, 2, __VA_ARGS__)
-
-typedef void (*sdl_func_t)(void);
-
-static sdl_func_t sdl_funcs[] = {
-	lcd_sdl, ser_sdl, vid_sdl
-};
-
-void sdl_init(void)
-{
-	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_TIMER) < 0) {
-		fprintf(stderr, "SDL_Init() failed: %s\n", SDL_GetError());
-		exit(1);
-	}
-
-	SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_VERBOSE);
-
-	if (SDLNet_Init() < 0) {
-		fail("SDLNet_Init() failed: %s", SDLNet_GetError());
-	}
-
-	if (TTF_Init() < 0) {
-		fail("TTF_Init() failed: %s", TTF_GetError());
-	}
-
-	SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
-	SDL_StartTextInput();
-}
-
-void sdl_quit(void)
-{
-	TTF_Quit();
-	SDLNet_Quit();
-	SDL_Quit();
-}
-
-void sdl_loop(void)
-{
-	inf("entering SDL loop");
-
-#if defined EMU_LINUX
-	SDL_Scancode down = SDL_SCANCODE_UNKNOWN;
-#endif
-
-	bool rel_mod = false;
-	uint32_t win = 0;
-
-	while (SDL_AtomicGet(&run) != 0) {
-		for (int32_t i = 0; i < ARRAY_COUNT(sdl_funcs); ++i) {
-			sdl_funcs[i]();
-		}
-
-		SDL_Event ev;
-
-		while (SDL_PollEvent(&ev) > 0) {
-			ver2("sdl ev %d", ev.type);
-
-#if defined EMU_LINUX
-			// Work around duplicate key-down events on Linux.
-
-			if (ev.type == SDL_KEYDOWN) {
-				if (down == ev.key.keysym.scancode) {
-					ver2("sdl dedup: skip %d", (int32_t)down);
-					continue;
-				}
-
-				down = ev.key.keysym.scancode;
-				ver2("sdl dedup: %d", (int32_t)down);
-			}
-			else if (ev.type == SDL_KEYUP) {
-				down = SDL_SCANCODE_UNKNOWN;
-				ver2("sdl dedup: reset");
-			}
-#endif
-
-			if (ev.type == SDL_QUIT ||
-					(ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_ESCAPE)) {
-				inf("quit event");
-				SDL_AtomicSet(&run, 0);
-				continue;
-			}
-
-			if (ev.type == SDL_WINDOWEVENT) {
-				if (ev.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) {
-					ver("sdl ev win %u", ev.window.windowID);
-					win = ev.window.windowID;
-				}
-			}
-
-			if (ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_DOWN) {
-				ver("sdl ev down-arrow");
-				rel_mod = true;
-				ser_mou_res();
-				continue;
-			}
-
-			if (ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_UP) {
-				ver("sdl ev up-arrow");
-				rel_mod = false;
-				continue;
-			}
-
-			if (rel_mod) {
-				if (ev.type == SDL_MOUSEMOTION) {
-					ver("sdl ev mousemotion (%d, %d)", ev.motion.xrel, ev.motion.yrel);
-					ser_mou_mov(&ev.motion);
-					continue;
-				}
-
-				if (ev.type == SDL_MOUSEBUTTONDOWN) {
-					ver("sdl ev mousebuttondown %d", ev.button.button);
-					ser_mou_dn(&ev.button);
-					continue;
-				}
-
-				if (ev.type == SDL_MOUSEBUTTONUP) {
-					ver("sdl ev mousebuttonup %d", ev.button.button);
-					ser_mou_up(&ev.button);
-					continue;
-				}
-			}
-
-			if (ev.type == SDL_TEXTINPUT) {
-				ver("sdl ev text input %d", ev.text.text[0]);
-
-				if (win == ser_win) {
-					ser_text(&ev.text);
-				}
-
-				continue;
-			}
-
-			if (ev.type == SDL_KEYDOWN) {
-				ver("sdl ev key down %d", (int32_t)ev.key.keysym.sym);
-
-				if (win == ser_win) {
-					ser_key(&ev.key);
-				}
-				else if (win == vid_win) {
-					kbd_key(&ev.key, true, true);
-				}
-				else if (win == lcd_win) {
-					kbd_key(&ev.key, false, true);
-				}
-
-				continue;
-			}
-
-			if (ev.type == SDL_KEYUP) {
-				ver("sdl ev key up %d", (int32_t)ev.key.keysym.sym);
-
-				if (win == vid_win) {
-					kbd_key(&ev.key, true, false);
-				}
-				else if (win == lcd_win) {
-					kbd_key(&ev.key, false, false);
-				}
-
-				continue;
-			}
-		}
-
-		SDL_Delay(50);
-
-		if (SDL_GetRelativeMouseMode() != rel_mod) {
-			SDL_SetRelativeMouseMode(rel_mod);
-
-			if (rel_mod) {
-				inf("MOUSE CAPTURED - press UP-ARROW KEY to release");
-			}
-			else {
-				inf("mouse released");
-			}
-		}
-	}
-
-	inf("leaving SDL loop");
-}
Index: u/ser.c
===================================================================
--- emu/ser.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,632 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <all.h>
-
-#define ver(...) _ver(ser_verbose, 0, __VA_ARGS__)
-#define ver2(...) _ver(ser_verbose, 1, __VA_ARGS__)
-#define ver3(...) _ver(ser_verbose, 2, __VA_ARGS__)
-
-int32_t ser_verbose = 0;
-
-#define WIN_W (1520 / 2)
-#define WIN_H (950 / 2)
-
-#define BEL_CYC 10000
-#define MOU_CYC 10000
-
-#if defined EMU_WIN
-#define MOU_DIV 64
-#elif defined EMU_OS_X
-#define MOU_DIV 1
-#else
-#define MOU_DIV 4
-#endif
-
-#define CON_W 80
-#define CON_H 25
-
-#define CON_BGR 0x00000000
-#define CON_BEL 0x00808080
-#define CON_CUR 0x00e87000
-#define CON_FGR ((SDL_Color){ .r = 255, .b = 255, .g = 255, .a = 255 })
-
-#define BUF_SZ 16
-
-#define REG_IER_ISR 0
-#define REG_CFR_SR  1
-#define REG_CDR_TBR 2
-#define REG_TDR_RDR 3
-
-typedef struct {
-	int32_t buf_hd;
-	int32_t buf_tl;
-	uint8_t buf[BUF_SZ];
-	bool irq_r;
-	bool irq_t;
-	bool rdr_ok;
-	uint8_t rdr;
-} state_t;
-
-static state_t state[] = {
-	{ .buf_hd = 0, .buf_tl = 0, .irq_r = false, .irq_t = false, .rdr_ok = false, .rdr = 0x00 },
-	{ .buf_hd = 0, .buf_tl = 0, .irq_r = false, .irq_t = false, .rdr_ok = false, .rdr = 0x00 }
-};
-
-static uint8_t mem[CON_H][CON_W];
-
-static SDL_Window *win;
-uint32_t ser_win;
-
-static SDL_Renderer *ren;
-static SDL_atomic_t frame;
-
-static TTF_Font *fon;
-static int32_t fon_w, fon_h;
-
-static int32_t sur_w, sur_h;
-static SDL_Surface *sur;
-
-static int32_t cur_x = 0, cur_y = 0;
-static int32_t bel = 0;
-
-static int32_t mou;
-static int32_t mou_dx, mou_dy;
-static bool mou_l, mou_r;
-
-static void scroll(void)
-{
-	memmove(mem, mem + 1, (CON_H - 1) * CON_W);
-	memset(mem + (CON_H - 1), ' ', CON_W);
-}
-
-static void forw(void)
-{
-	if (cur_x < CON_W - 1) {
-		++cur_x;
-		return;
-	}
-
-	if (cur_y == CON_H - 1) {
-		cur_x = 0;
-		scroll();
-		return;
-	}
-
-	cur_x = 0;
-	++cur_y;
-}
-
-static void back(void)
-{
-	if (cur_x > 0) {
-		--cur_x;
-		return;
-	}
-
-	if (cur_y == 0) {
-		return;
-	}
-
-	cur_x = CON_W - 1;
-	--cur_y;
-}
-
-static void down(void)
-{
-	if (cur_y < CON_H - 1) {
-		++cur_y;
-		return;
-	}
-
-	scroll();
-}
-
-static void echo(uint8_t c)
-{
-	if (c < 32) {
-		switch (c) {
-		case '\r':
-			cur_x = 0;
-			break;
-
-		case '\n':
-			down();
-			break;
-
-		case '\b':
-			back();
-			break;
-
-		case '\a':
-			bel = BEL_CYC;
-			break;
-
-		default:
-			echo('^');
-			echo((uint8_t)(c + '@'));
-			return;
-		}
-	}
-	else {
-		mem[cur_y][cur_x] = c;
-		forw();
-	}
-
-	SDL_AtomicAdd(&frame, 1);
-}
-
-static void xmit(int32_t un)
-{
-	int32_t i = state[un].buf_tl;
-	ver2("ser xmit %d %d", i, state[un].buf_hd);
-
-	if (i >= state[un].buf_hd) {
-		return;
-	}
-
-	uint8_t byte = state[un].buf[i % BUF_SZ];
-	ver2("ser xmit 0x%02x", byte);
-
-	state[un].rdr = byte;
-	state[un].rdr_ok = true;
-	state[un].irq_r = true;
-
-	state[un].buf_tl = i + 1;
-
-	if (state[un].buf_tl >= BUF_SZ) {
-		state[un].buf_hd -= BUF_SZ;
-		state[un].buf_tl -= BUF_SZ;
-		ver2("ser adj %d %d", state[un].buf_tl, state[un].buf_hd);
-	}
-}
-
-static void out_lk(int32_t un, uint8_t c)
-{
-	int32_t i = state[un].buf_hd;
-	ver2("ser out %d %d 0x%02x", state[un].buf_tl, i, c);
-
-	if (i >= state[un].buf_tl + BUF_SZ) {
-		err("serial port %d losing data", un);
-		return;
-	}
-
-	state[un].buf[i % BUF_SZ] = c;
-	state[un].buf_hd = i + 1;
-
-	if (!state[un].irq_r && !state[un].rdr_ok) {
-		xmit(un);
-	}
-}
-
-static void out(int32_t un, uint8_t c)
-{
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	out_lk(un, c);
-
-	if (SDL_UnlockMutex(cpu_mutex) < 0) {
-		fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-	}
-}
-
-static void mouse(uint8_t c)
-{
-	if (c == 't') {
-		ver2("ser mou init");
-	}
-
-	out_lk(0, 'V');
-	out_lk(0, 'O');
-}
-
-void ser_sdl(void)
-{
-	ver3("ser_sdl()");
-
-	static int32_t last = 0;
-	int32_t now = SDL_AtomicGet(&frame);
-
-	if (last == now) {
-		ver3("no update");
-		return;
-	}
-
-	last = now;
-
-	if (SDL_FillRect(sur, NULL, bel == 0 ? CON_BGR : CON_BEL) < 0) {
-		fail("SDL_FillRect() failed: %s", SDL_GetError());
-	}
-
-	if (SDL_FillRect(sur, &(SDL_Rect){
-		.x = cur_x * fon_w,
-		.y = cur_y * fon_h,
-		.w = fon_w,
-		.h = fon_h
-	}, CON_CUR) < 0) {
-		fail("SDL_FillRect() failed: %s", SDL_GetError());
-	}
-
-	for (int32_t y = 0; y < CON_H; ++y) {
-		char line[CON_W + 1];
-		line[CON_W] = 0;
-
-		if (SDL_LockMutex(cpu_mutex) < 0) {
-			fail("SDL_LockMutex() failed: %s", SDL_GetError());
-		}
-
-		memcpy(line, mem[y], CON_W);
-
-		if (SDL_UnlockMutex(cpu_mutex) < 0) {
-			fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-		}
-
-		SDL_Surface *lin = TTF_RenderText_Blended(fon, line, CON_FGR);
-
-		if (lin == NULL) {
-			fail("TTF_RenderText_Blended() failed: %s", TTF_GetError());
-		}
-
-		if (SDL_BlitSurface(lin, NULL, sur, &(SDL_Rect){
-			.x = 0,
-			.y = y * fon_h,
-			.w = CON_W * fon_w,
-			.h = fon_h
-		})) {
-			fail("SDL_BlitSurface() failed: %s", SDL_GetError());
-		}
-
-		SDL_FreeSurface(lin);
-	}
-
-	SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, sur);
-
-	if (tex == NULL) {
-		fail("SDL_CreateTextureFromSurface() failed: %s", SDL_GetError());
-	}
-
-	if (SDL_RenderCopy(ren, tex, NULL, NULL) < 0) {
-		fail("SDL_RenderCopy() failed: %s", SDL_GetError());
-	}
-
-	SDL_DestroyTexture(tex);
-	SDL_RenderPresent(ren);
-}
-
-void ser_key(SDL_KeyboardEvent *ev)
-{
-	switch (ev->keysym.sym) {
-	case SDLK_BACKSPACE:
-		out(1, '\b');
-		break;
-
-	case SDLK_RETURN:
-		out(1, '\r');
-		break;
-
-	default:
-		if ((ev->keysym.mod & KMOD_CTRL) != 0 &&
-				ev->keysym.sym >= SDLK_a && ev->keysym.sym <= SDLK_z) {
-			out(1, (uint8_t)(ev->keysym.sym - SDLK_a + 1));
-		}
-
-		break;
-	}
-}
-
-void ser_text(SDL_TextInputEvent *ev)
-{
-	for (int32_t i = 0; ev->text[i] != 0; ++i) {
-		out(1, (uint8_t)ev->text[i]);
-	}
-}
-
-static void mou_ev(void)
-{
-	ver2("ser mou ev (%d, %d) %c %c",
-		mou_dx, mou_dy, mou_l ? 'l' : '-', mou_r ? 'r' : '-');
-
-	int32_t dx = mou_dx / MOU_DIV;
-	int32_t dy = mou_dy / MOU_DIV;
-
-	if (dx < -128) {
-		dx = -128;
-	}
-	else if (dx > 127) {
-		dx = 127;
-	}
-
-	if (dy < -128) {
-		dy = -128;
-	}
-	else if (dy > 127) {
-		dy = 127;
-	}
-
-	dx = dx & 0xff;
-	dy = dy & 0xff;
-
-	int32_t b1 = 0x40;
-
-	if (mou_l) {
-		b1 |= 0x20;
-	}
-
-	if (mou_r) {
-		b1 |= 0x10;
-	}
-
-	b1 |= (dy & 0xc0) >> 4;
-	b1 |= (dx & 0xc0) >> 6;
-
-	int32_t b2 = dx & 0x3f;
-	int32_t b3 = dy & 0x3f;
-
-	out_lk(0, (uint8_t)b1);
-	out_lk(0, (uint8_t)b2);
-	out_lk(0, (uint8_t)b3);
-
-	mou_dx = mou_dy = 0;
-}
-
-static void mou_ev_chk(void)
-{
-	if (--mou > 0) {
-		return;
-	}
-
-	mou = MOU_CYC;
-
-	if (mou_dx == 0 && mou_dy == 0) {
-		return;
-	}
-
-	mou_ev();
-}
-
-void ser_mou_res(void)
-{
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	mou = MOU_CYC;
-	mou_dx = mou_dy = 0;
-	mou_l = mou_r = false;
-
-	if (SDL_UnlockMutex(cpu_mutex) < 0) {
-		fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-	}
-}
-
-void ser_mou_mov(SDL_MouseMotionEvent *ev)
-{
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	mou_dx += ev->xrel;
-	mou_dy += ev->yrel;
-
-	if (SDL_UnlockMutex(cpu_mutex) < 0) {
-		fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-	}
-}
-
-void ser_mou_dn(SDL_MouseButtonEvent *ev)
-{
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	if (ev->button == SDL_BUTTON_LEFT) {
-		mou_l = true;
-	}
-	else if (ev->button == SDL_BUTTON_RIGHT) {
-		mou_r = true;
-	}
-	else {
-		return;
-	}
-
-	mou_ev();
-
-	if (SDL_UnlockMutex(cpu_mutex) < 0) {
-		fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-	}
-}
-
-void ser_mou_up(SDL_MouseButtonEvent *ev)
-{
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	if (ev->button == SDL_BUTTON_LEFT) {
-		mou_l = false;
-	}
-	else if (ev->button == SDL_BUTTON_RIGHT) {
-		mou_r = false;
-	}
-	else {
-		return;
-	}
-
-	mou_ev();
-
-	if (SDL_UnlockMutex(cpu_mutex) < 0) {
-		fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-	}
-}
-
-void ser_init(void)
-{
-	ver("ser init");
-
-	win = SDL_CreateWindow("Serial Console", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
-			WIN_W, WIN_H, 0);
-
-	if (win == NULL) {
-		fail("SDL_CreateWindow() failed: %s", SDL_GetError());
-	}
-
-	ser_win = SDL_GetWindowID(win);
-
-	if (ser_win == 0) {
-		fail("SDL_GetWindowID() failed: %s", SDL_GetError());
-	}
-
-	ren = SDL_CreateRenderer(win, -1, 0);
-
-	if (ren == NULL) {
-		fail("SDL_CreateRenderer() failed: %s", SDL_GetError());
-	}
-
-	SDL_AtomicSet(&frame, 1);
-
-	SDL_RWops *ops = SDL_RWFromFile(font, "rb");
-
-	if (ops == NULL) {
-		fail("error while opening font file %s: %s", font, SDL_GetError());
-	}
-
-	fon = TTF_OpenFontRW(ops, 1, 32);
-
-	if (fon == NULL) {
-		fail("error while loading font file %s: %s", font, TTF_GetError());
-	}
-
-	fon_h = TTF_FontLineSkip(fon);
-
-	if (TTF_GlyphMetrics(fon, 'X', NULL, NULL, NULL, NULL, &fon_w) < 0) {
-		fail("error while measuring font width: %s", TTF_GetError());
-	}
-
-	sur_w = CON_W * fon_w;
-	sur_h = CON_H * fon_h;
-
-	sur = SDL_CreateRGBSurface(0, sur_w, sur_h, 32, 0, 0, 0, 0);
-
-	if (sur == NULL) {
-		fail("SDL_CreateRGBSurface() failed: %s", SDL_GetError());
-	}
-
-	for (int32_t y = 0; y < CON_H; ++y) {
-		for (int32_t x = 0; x < CON_W; ++x) {
-			mem[y][x] = ' ';
-		}
-	}
-}
-
-void ser_quit(void)
-{
-	ver("ser quit");
-
-	SDL_FreeSurface(sur);
-	TTF_CloseFont(fon);
-
-	SDL_DestroyRenderer(ren);
-	SDL_DestroyWindow(win);
-}
-
-bool ser_exec(void)
-{
-	ver3("ser exec");
-
-	if (bel > 0) {
-		--bel;
-
-		if (bel == BEL_CYC - 1 || bel == 0) {
-			SDL_AtomicAdd(&frame, 1);
-		}
-	}
-
-	mou_ev_chk();
-
-	return state[0].irq_r || state[0].irq_t || state[1].irq_r || state[1].irq_t;
-}
-
-uint32_t ser_read(uint32_t off, int32_t sz)
-{
-	ver2("ser rd %u:%d", off, sz * 8);
-
-	if (sz != 1 || off > 7) {
-		fail("invalid ser rd %u:%d", off, sz * 8);
-	}
-
-	int32_t rg = (int32_t)(off % 4);
-	int32_t un = (int32_t)(off / 4);
-
-	uint32_t rv;
-
-	switch (rg) {
-	case REG_IER_ISR:
-		rv = (uint32_t)(0xc0 | (state[un].rdr_ok ? 0x01 : 0x00));
-		state[un].irq_r = false;
-		state[un].irq_t = false;
-		ver2("ISR[%d] 0x%02x", un, rv);
-		break;
-
-	case REG_TDR_RDR:
-		rv = state[un].rdr;
-		state[un].rdr_ok = false;
-		ver2("RDR[%d] 0x%02x", un, rv);
-		break;
-
-	default:
-		rv = 0x00;
-		break;
-	}
-
-	if (!state[un].irq_r && !state[un].rdr_ok) {
-		xmit(un);
-	}
-
-	return rv;
-}
-
-void ser_write(uint32_t off, int32_t sz, uint32_t val)
-{
-	ver2("ser wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
-
-	if (sz != 1 || off > 7) {
-		fail("invalid ser wr %u:%d", off, sz * 8);
-	}
-
-	int32_t rg = (int32_t)(off % 4);
-	int32_t un = (int32_t)(off / 4);
-
-	switch (rg) {
-	case REG_TDR_RDR:
-		ver2("TDR[%d] 0x%02x", un, val);
-
-		if (un == 1) {
-			echo((uint8_t)val);
-		}
-		else {
-			mouse((uint8_t)val);
-		}
-
-		state[un].irq_t = true;
-		break;
-
-	default:
-		break;
-	}
-}
Index: u/snd.c
===================================================================
--- emu/snd.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,51 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <all.h>
-
-#define ver(...) _ver(snd_verbose, 0, __VA_ARGS__)
-#define ver2(...) _ver(snd_verbose, 1, __VA_ARGS__)
-#define ver3(...) _ver(snd_verbose, 2, __VA_ARGS__)
-
-int32_t snd_verbose = 0;
-
-void snd_init(void)
-{
-	ver("snd init");
-}
-
-void snd_quit(void)
-{
-	ver("snd quit");
-}
-
-bool snd_exec(void)
-{
-	ver3("snd exec");
-	return false;
-}
-
-uint32_t snd_read(uint32_t off, int32_t sz)
-{
-	ver2("snd rd %u:%d", off, sz * 8);
-	return 0;
-}
-
-void snd_write(uint32_t off, int32_t sz, uint32_t val)
-{
-	ver2("snd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
-}
Index: u/tim.c
===================================================================
--- emu/tim.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,169 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <all.h>
-
-#define ver(...) _ver(tim_verbose, 0, __VA_ARGS__)
-#define ver2(...) _ver(tim_verbose, 1, __VA_ARGS__)
-#define ver3(...) _ver(tim_verbose, 2, __VA_ARGS__)
-
-int32_t tim_verbose = 0;
-
-#define REG_CRX 0
-#define REG_CR2_SR 1
-#define REG_T1H	2
-#define REG_T1L 3
-#define REG_T2H 4
-#define REG_T2L 5
-#define REG_T3H 6
-#define REG_T3L 7
-
-#define COUNT_1 32
-#define COUNT_2 3200
-#define COUNT_3 801
-
-typedef struct {
-	bool irq_e;
-	bool irq;
-	int32_t latch;
-	int32_t count;
-} state_timer;
-
-static state_timer timers[] = {
-		{ .irq_e = false, .irq = false, .latch = COUNT_1, .count = COUNT_1 },
-		{ .irq_e = false, .irq = false, .latch = COUNT_2, .count = COUNT_2 },
-		{ .irq_e = false, .irq = false, .latch = COUNT_3, .count = COUNT_3 }
-};
-
-static bool wr_cr1 = false;
-static bool oper = false;
-
-void tim_init(void)
-{
-	ver("tim init");
-}
-
-void tim_quit(void)
-{
-	ver("tim quit");
-}
-
-bool tim_exec(void)
-{
-	if (oper) {
-		for (int32_t i = 0; i < ARRAY_COUNT(timers); ++i) {
-			--timers[i].count;
-
-			if (timers[i].count == 0) {
-				ver2("tim %d zero", i + 1);
-				timers[i].count = timers[i].latch;
-
-				if (timers[i].irq_e) {
-					ver2("tim %d irq", i + 1);
-					timers[i].irq = true;
-				}
-			}
-		}
-	}
-
-	return timers[0].irq || timers[1].irq || timers[2].irq;
-}
-
-uint32_t tim_read(uint32_t off, int32_t sz)
-{
-	ver2("tim rd %u:%d", off, sz * 8);
-
-	if (sz != 1 || off > 7) {
-		fail("invalid tim rd %u:%d", off, sz * 8);
-	}
-
-	uint32_t rv = 0x00;
-
-	switch (off) {
-	case REG_CR2_SR:
-		rv |= (uint32_t)timers[0].irq << 0;
-		rv |= (uint32_t)timers[1].irq << 1;
-		rv |= (uint32_t)timers[2].irq << 2;
-
-		ver2("tim irqs %u %u %u",
-				(uint32_t)timers[0].irq, (uint32_t)timers[1].irq, (uint32_t)timers[2].irq);
-		break;
-
-	case REG_T1L:
-		if (timers[0].irq) {
-			ver2("tim 1 !irq");
-			timers[0].irq = false;
-		}
-
-		break;
-
-	case REG_T2L:
-		if (timers[1].irq) {
-			ver2("tim 2 !irq");
-			timers[1].irq = false;
-		}
-
-		break;
-
-	case REG_T3L:
-		if (timers[2].irq) {
-			ver2("tim 3 !irq");
-			timers[2].irq = false;
-		}
-
-		break;
-
-	default:
-		break;
-	}
-
-	return rv;
-}
-
-void tim_write(uint32_t off, int32_t sz, uint32_t val)
-{
-	ver2("tim wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
-
-	if (sz != 1 || off > 7) {
-		fail("invalid tim wr %u:%d", off, sz * 8);
-	}
-
-	switch (off) {
-	case REG_CRX:
-		if (wr_cr1) {
-			if ((val & 0x01) == 0) {
-				ver2("tim start");
-				oper = true;
-			}
-
-			timers[0].irq_e = (val & 0x40) != 0;
-		}
-		else {
-			timers[2].irq_e = (val & 0x40) != 0;
-		}
-
-		break;
-
-	case REG_CR2_SR:
-		wr_cr1 = (val & 0x01) != 0;
-		timers[1].irq_e = (val & 0x40) != 0;
-		break;
-
-	default:
-		break;
-	}
-}
Index: u/vid.c
===================================================================
--- emu/vid.c	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,468 +1,0 @@
-/*
- *  Copyright (C) 2017 The Contributors
- *
- *  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 3 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.
- *
- *  A copy of the GNU General Public License can be found in the file
- *  "gpl.txt" in the top directory of this repository.
- */
-
-#include <all.h>
-
-#define ver(...) _ver(vid_verbose, 0, __VA_ARGS__)
-#define ver2(...) _ver(vid_verbose, 1, __VA_ARGS__)
-#define ver3(...) _ver(vid_verbose, 2, __VA_ARGS__)
-
-int32_t vid_verbose = 0;
-
-#define SCR_W 512
-#define SCR_H 350
-#define VBL_H 50
-
-#define REG_VCR0 0
-#define REG_VCR1 1
-#define REG_RWBA 2
-#define REG_DSBA 5
-#define REG_ODTBA 7
-#define REG_ATBA 8
-#define REG_CGBA 10
-#define REG_ATBAC 11
-
-#define VCR0_UCF 0x0001
-#define VCR0_DEN 0x0008
-
-#define DSBA_BS1 0x0080
-#define DSBA_BS0 0x0100
-
-#define REG_OFF 0x200
-#define PAL_OFF 0x40000
-
-#define OD0_TDE 0x0004
-#define OD0_BLA 0x0010
-#define OD0_CB 0x0800
-
-#define AT_UND 0x0100
-#define AT_CG 0x8000
-
-#define WIN_SZ_W 0x10000
-#define MEM_SZ_W 0x20000
-
-#define N_BANKS 2
-
-#define SCALE(_x) (_x * 2)
-
-#define WIN_W SCALE(SCR_W)
-#define WIN_H SCALE(SCR_H)
-
-typedef struct {
-	int32_t y, h;
-} ver_t;
-
-typedef struct {
-	int32_t x, w;
-	int32_t n_vers;
-	ver_t vers[SCR_H / 2];
-	uint16_t *mem;
-	bool tran;
-	int32_t fon_h;
-} obj_t;
-
-static int32_t reg_off = REG_OFF;
-
-static uint16_t mem[MEM_SZ_W];
-static int32_t bank = 0;
-
-static uint32_t pal[16];
-
-static obj_t objs[16];
-static int32_t n_objs = 0;
-
-static SDL_Window *win;
-uint32_t vid_win;
-
-static SDL_Renderer *ren;
-static SDL_Texture *tex;
-static SDL_atomic_t frame;
-
-static uint16_t *rend_bm(uint16_t *vid, int32_t w, int32_t h, uint32_t *pix, int32_t pitch)
-{
-	for (int32_t y = 0; y < h; ++y) {
-		for (int32_t x = 0; x < w / 4; ++x) {
-			uint16_t v4 = *vid++;
-
-			*pix++ = pal[(v4 & 0x000f) >>  0];
-			*pix++ = pal[(v4 & 0x00f0) >>  4];
-			*pix++ = pal[(v4 & 0x0f00) >>  8];
-			*pix++ = pal[(v4 & 0xf000) >> 12];
-		}
-
-		pix += pitch / 4 - w;
-	}
-
-	return vid;
-}
-
-static uint16_t *rend_tx(uint16_t *vid, int32_t w, int32_t h, int32_t fon_h,
-		uint32_t *pix, int32_t pitch)
-{
-	int32_t cgba = mem[REG_CGBA];
-
-	uint16_t *cg0 = mem + ((cgba & 0x00f0) <<  8);
-	uint16_t *cg1 = mem + ((cgba & 0x000f) << 12);
-
-	int32_t line = fon_h - 1;
-
-	for (int32_t y = 0; y < h; ++y) {
-		uint16_t *walk = vid;
-
-		for (int32_t col2 = 0; col2 < w / 16; ++col2) {
-			uint16_t ch2 = *walk++;
-
-			for (int32_t i = 0; i < 2; ++i) {
-				int32_t ch = (uint8_t)ch2;
-				int32_t at = *walk++;
-
-				int32_t bg = at & 0x000f;
-				int32_t fg = (at & 0x00f0) >> 4;
-
-				int32_t bits;
-
-				if ((at & AT_UND) != 0 && line == 1) {
-					bits = 0xff;
-				}
-				else {
-					uint16_t *cg = (at & AT_CG) != 0 ? cg0 : cg1;
-					bits = cg[256 * line + ch];
-				}
-
-				int32_t mask = 0x01;
-
-				for (int32_t k = 0; k < 8; ++k) {
-					*pix++ = (bits & mask) != 0 ? pal[fg] : pal[bg];
-					mask <<= 1;
-				}
-
-				ch2 >>= 8;
-			}
-		}
-
-		if (--line < 0) {
-			line = fon_h - 1;
-			vid = walk;
-		}
-
-		pix += pitch / 4 - w;
-	}
-
-	return vid;
-}
-
-void vid_sdl(void)
-{
-	ver3("vid_sdl()");
-
-	static int32_t last = 0;
-	int32_t now = SDL_AtomicGet(&frame);
-
-	if (last == now) {
-		ver3("no update");
-		return;
-	}
-
-	last = now;
-
-	if (SDL_RenderFillRect(ren, NULL) < 0) {
-		fail("SDL_RenderFillRect() failed: %s", SDL_GetError());
-	}
-
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	for (int32_t i = 0; i < n_objs; ++i) {
-		obj_t *obj = objs + i;
-
-		pal[0] = obj->tran ? pal[0] & 0xffffff00 : pal[0] | 0x000000ff;
-		uint16_t *m = obj->mem;
-
-		for (int32_t k = 0; k < obj->n_vers; ++k) {
-			SDL_Rect src = {
-				.x = 0, .y = 0, .w = obj->w, .h = obj->vers[k].h
-			};
-
-			void *buf;
-			int32_t pitch;
-
-			if (SDL_LockTexture(tex, &src, &buf, &pitch) < 0) {
-				fail("SDL_LockTexture() failed: %s", SDL_GetError());
-			}
-
-			if (obj->fon_h < 0) {
-				m = rend_bm(m, obj->w, obj->vers[k].h, buf, pitch);
-			}
-			else {
-				m = rend_tx(m, obj->w, obj->vers[k].h, obj->fon_h, buf, pitch);
-			}
-
-			SDL_UnlockTexture(tex);
-
-			SDL_Rect dst = {
-				.x = SCALE(obj->x), .y = SCALE(obj->vers[k].y),
-				.w = SCALE(obj->w), .h = SCALE(obj->vers[k].h)
-			};
-
-			ver2("vid rend %d %d %dx%d -> (%d, %d) (%d, %d) %dx%d",
-					i, k,
-					obj->w, obj->vers[k].h,
-					obj->x, obj->vers[k].y,
-					SCALE(obj->x), SCALE(obj->vers[k].y),
-					SCALE(obj->w), SCALE(obj->vers[k].h));
-
-			if (SDL_RenderCopy(ren, tex, &src, &dst) < 0) {
-				fail("SDL_RenderCopy() failed: %s", SDL_GetError());
-			}
-		}
-	}
-
-	if (SDL_UnlockMutex(cpu_mutex) < 0) {
-		fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
-	}
-
-	SDL_RenderPresent(ren);
-}
-
-void vid_init(void)
-{
-	ver("vid init");
-
-	win = SDL_CreateWindow("Screen", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
-			WIN_W, WIN_H, 0);
-
-	if (win == NULL) {
-		fail("SDL_CreateWindow() failed: %s", SDL_GetError());
-	}
-
-	vid_win = SDL_GetWindowID(win);
-
-	if (vid_win == 0) {
-		fail("SDL_GetWindowID() failed: %s", SDL_GetError());
-	}
-
-	ren = SDL_CreateRenderer(win, -1, 0);
-
-	if (ren == NULL) {
-		fail("SDL_CreateRenderer() failed: %s", SDL_GetError());
-	}
-
-	if (SDL_SetRenderDrawColor(ren, 0x00, 0x00, 0x00, 0xff) < 0) {
-		fail("SDL_SetRenderDrawColor() failed: %s", SDL_GetError());
-	}
-
-	tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING,
-			SCR_W, SCR_H);
-
-	if (tex == NULL) {
-		fail("SDL_CreateTexture() failed: %s", SDL_GetError());
-	}
-
-	if (SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND) < 0) {
-		fail("SDL_SetTextureBlendMode() failed: %s", SDL_GetError());
-	}
-
-	SDL_AtomicSet(&frame, 1);
-}
-
-void vid_quit(void)
-{
-	ver("vid quit");
-
-	SDL_DestroyTexture(tex);
-	SDL_DestroyRenderer(ren);
-	SDL_DestroyWindow(win);
-}
-
-bool vid_exec(void)
-{
-	ver3("vid exec");
-
-	static int32_t skip = 99999;
-	static int32_t line = 99999;
-
-	if (++skip < 10) {
-		ver3("vid skip %d", skip);
-		return false;
-	}
-
-	skip = 0;
-	int32_t vcr0 = mem[REG_VCR0];
-
-	if ((vcr0 & VCR0_DEN) == 0) {
-		ver3("vid dis");
-		return false;
-	}
-
-	if (++line < SCR_H + VBL_H) {
-		ver3("vid line %d", line);
-
-		if (line < SCR_H) {
-			++mem[REG_ATBAC];
-		}
-
-		return line == SCR_H;
-	}
-
-	// We get here every 4,000 invocations -> 25 fps.
-
-	ver2("vid frame");
-	line = 0;
-
-	int32_t dsba = mem[REG_DSBA];
-	bank = ((dsba & DSBA_BS0) != 0 ? 1 : 0) + ((dsba & DSBA_BS1) != 0 ? 2 : 0);
-
-	int32_t rwba = mem[REG_RWBA];
-	reg_off = (rwba & 0xfff0) << 1;
-
-	int32_t atba = mem[REG_ATBA];
-	mem[REG_ATBAC] = (uint16_t)atba;
-
-	int32_t odtba = mem[REG_ODTBA] & 0xffc0;
-
-	n_objs = 0;
-
-	for (int32_t i = 0; i < 16; ++i) {
-		int32_t flips[SCR_H];
-		int32_t n_flips = 0;
-
-		uint16_t *od = mem + odtba + 4 * i;
-
-		if ((od[0] & OD0_BLA) != 0) {
-			ver3("vid obj %d blanked", i);
-			continue;
-		}
-
-		int32_t w64 = (od[1] & 0xfc00) >> 10;
-
-		if (w64 == 0) {
-			ver3("vid obj %d empty", i);
-			continue;
-		}
-
-		int32_t mask = 1 << i;
-
-		for (int32_t k = 0; k < SCR_H; ++k) {
-			if ((mem[atba + k] & mask) == 0) {
-				flips[n_flips] = k;
-				++n_flips;
-			}
-		}
-
-		if (n_flips == 0) {
-			ver3("vid obj %d unused", i);
-			continue;
-		}
-
-		if (n_flips % 2 != 0) {
-			flips[n_flips] = SCR_H;
-			++n_flips;
-		}
-
-		bool cb = (od[0] & OD0_CB) != 0;
-		bool tde = (od[0] & OD0_TDE) != 0;
-
-		int32_t x = (od[1] & 0x03ff) * 2;
-		int32_t off, fon_h, w;
-
-		if (cb) {
-			off = od[2];
-			int32_t vcr1 = mem[REG_VCR1];
-			fon_h = (vcr1 & 0xf000) >> 12;
-			w = w64 * 4 / 3 * 2 * 8;
-		}
-		else {
-			off = ((od[0] & 0x00c0) << 10) | od[2];
-			fon_h = -1;
-			w = w64 * 16;
-		}
-
-		obj_t *obj = objs + n_objs;
-
-		obj->x = x;
-		obj->w = w;
-		obj->n_vers = n_flips / 2;
-
-		for (int32_t k = 0; k < obj->n_vers; ++k) {
-			obj->vers[k].y = flips[2 * k];
-			obj->vers[k].h = flips[2 * k + 1] - flips[2 * k];
-		}
-
-		obj->mem = mem + off;
-		obj->tran = tde;
-		obj->fon_h = fon_h;
-
-		ver2("vid obj %d %c %c %d:%d %d+%d %d 0x%05x",
-				i, cb ? 'c' : 'b', tde ? 't' : '-', flips[0], flips[1], x, w, fon_h, off);
-
-		++n_objs;
-	}
-
-	SDL_AtomicAdd(&frame, 1);
-	return false;
-}
-
-uint32_t vid_read(uint32_t off, int32_t sz)
-{
-	ver2("vid rd %d 0x%05x:%d", bank, off, sz * 8);
-
-	int32_t off16 = (int32_t)(off / 2);
-
-	if (sz != 2 || bank >= N_BANKS || off % 2 != 0 || off16 >= WIN_SZ_W) {
-		fail("invalid vid rd %d %u:%d", bank, off, sz * 8);
-	}
-
-	if (off16 >= reg_off && off16 < reg_off + 16) {
-		return mem[off16 - reg_off];
-	}
-
-	return mem[bank * WIN_SZ_W + off16];
-}
-
-void vid_write(uint32_t off, int32_t sz, uint32_t val)
-{
-	ver2("vid wr %d 0x%05x:%d 0x%0*x", bank, off, sz * 8, sz * 2, val);
-
-	int32_t off16 = (int32_t)(off / 2);
-
-	if (sz != 2 || bank >= N_BANKS || off % 2 != 0 || (off16 >= WIN_SZ_W && off16 != PAL_OFF)) {
-		fail("invalid vid wr %d %u:%d", bank, off, sz * 8);
-	}
-
-	if (off16 == PAL_OFF) {
-		int32_t i_pal = ((int32_t)val & 0x03c0) >> 6;
-
-		uint32_t r = ((val & 0x0004) >> 1) | ((val & 0x0020) >> 5);
-		uint32_t g = ((val & 0x0002) >> 0) | ((val & 0x0010) >> 4);
-		uint32_t b = ((val & 0x0001) << 1) | ((val & 0x0008) >> 3);
-
-		r = (r ^ 3) * 85;
-		g = (g ^ 3) * 85;
-		b = (b ^ 3) * 85;
-
-		pal[i_pal] = (r << 24) | (g << 16) | (b << 8) | 0xff;
-		return;
-	}
-
-	if (off16 >= reg_off && off16 < reg_off + 16) {
-		mem[off16 - reg_off] = (uint16_t)val;
-		return;
-	}
-
-	mem[bank * WIN_SZ_W + off16] = (uint16_t)val;
-}
Index: l.txt
===================================================================
--- gpl.txt	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,674 +1,0 @@
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
-  The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works.  By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.  We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors.  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
-  To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights.  Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received.  You must make sure that they, too, receive
-or can get the source code.  And you must show them these terms so they
-know their rights.
-
-  Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
-  For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software.  For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
-  Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so.  This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software.  The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable.  Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products.  If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
-  Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary.  To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                       TERMS AND CONDITIONS
-
-  0. Definitions.
-
-  "This License" refers to version 3 of the GNU General Public License.
-
-  "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
-  "The Program" refers to any copyrightable work licensed under this
-License.  Each licensee is addressed as "you".  "Licensees" and
-"recipients" may be individuals or organizations.
-
-  To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy.  The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
-  A "covered work" means either the unmodified Program or a work based
-on the Program.
-
-  To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy.  Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
-  To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies.  Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
-  An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License.  If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
-  1. Source Code.
-
-  The "source code" for a work means the preferred form of the work
-for making modifications to it.  "Object code" means any non-source
-form of a work.
-
-  A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
-  The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form.  A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
-  The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities.  However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work.  For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
-  The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
-  The Corresponding Source for a work in source code form is that
-same work.
-
-  2. Basic Permissions.
-
-  All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met.  This License explicitly affirms your unlimited
-permission to run the unmodified Program.  The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work.  This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
-  You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force.  You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright.  Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
-  Conveying under any other circumstances is permitted solely under
-the conditions stated below.  Sublicensing is not allowed; section 10
-makes it unnecessary.
-
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
-  No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
-  When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
-  4. Conveying Verbatim Copies.
-
-  You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
-  You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
-  5. Conveying Modified Source Versions.
-
-  You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
-    a) The work must carry prominent notices stating that you modified
-    it, and giving a relevant date.
-
-    b) The work must carry prominent notices stating that it is
-    released under this License and any conditions added under section
-    7.  This requirement modifies the requirement in section 4 to
-    "keep intact all notices".
-
-    c) You must license the entire work, as a whole, under this
-    License to anyone who comes into possession of a copy.  This
-    License will therefore apply, along with any applicable section 7
-    additional terms, to the whole of the work, and all its parts,
-    regardless of how they are packaged.  This License gives no
-    permission to license the work in any other way, but it does not
-    invalidate such permission if you have separately received it.
-
-    d) If the work has interactive user interfaces, each must display
-    Appropriate Legal Notices; however, if the Program has interactive
-    interfaces that do not display Appropriate Legal Notices, your
-    work need not make them do so.
-
-  A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit.  Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
-  6. Conveying Non-Source Forms.
-
-  You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
-    a) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by the
-    Corresponding Source fixed on a durable physical medium
-    customarily used for software interchange.
-
-    b) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by a
-    written offer, valid for at least three years and valid for as
-    long as you offer spare parts or customer support for that product
-    model, to give anyone who possesses the object code either (1) a
-    copy of the Corresponding Source for all the software in the
-    product that is covered by this License, on a durable physical
-    medium customarily used for software interchange, for a price no
-    more than your reasonable cost of physically performing this
-    conveying of source, or (2) access to copy the
-    Corresponding Source from a network server at no charge.
-
-    c) Convey individual copies of the object code with a copy of the
-    written offer to provide the Corresponding Source.  This
-    alternative is allowed only occasionally and noncommercially, and
-    only if you received the object code with such an offer, in accord
-    with subsection 6b.
-
-    d) Convey the object code by offering access from a designated
-    place (gratis or for a charge), and offer equivalent access to the
-    Corresponding Source in the same way through the same place at no
-    further charge.  You need not require recipients to copy the
-    Corresponding Source along with the object code.  If the place to
-    copy the object code is a network server, the Corresponding Source
-    may be on a different server (operated by you or a third party)
-    that supports equivalent copying facilities, provided you maintain
-    clear directions next to the object code saying where to find the
-    Corresponding Source.  Regardless of what server hosts the
-    Corresponding Source, you remain obligated to ensure that it is
-    available for as long as needed to satisfy these requirements.
-
-    e) Convey the object code using peer-to-peer transmission, provided
-    you inform other peers where the object code and Corresponding
-    Source of the work are being offered to the general public at no
-    charge under subsection 6d.
-
-  A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
-  A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling.  In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage.  For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product.  A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
-  "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source.  The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
-  If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information.  But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
-  The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed.  Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
-  Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
-  7. Additional Terms.
-
-  "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law.  If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-  When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it.  (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.)  You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
-  Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
-    a) Disclaiming warranty or limiting liability differently from the
-    terms of sections 15 and 16 of this License; or
-
-    b) Requiring preservation of specified reasonable legal notices or
-    author attributions in that material or in the Appropriate Legal
-    Notices displayed by works containing it; or
-
-    c) Prohibiting misrepresentation of the origin of that material, or
-    requiring that modified versions of such material be marked in
-    reasonable ways as different from the original version; or
-
-    d) Limiting the use for publicity purposes of names of licensors or
-    authors of the material; or
-
-    e) Declining to grant rights under trademark law for use of some
-    trade names, trademarks, or service marks; or
-
-    f) Requiring indemnification of licensors and authors of that
-    material by anyone who conveys the material (or modified versions of
-    it) with contractual assumptions of liability to the recipient, for
-    any liability that these contractual assumptions directly impose on
-    those licensors and authors.
-
-  All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10.  If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term.  If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
-  If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
-  Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
-  8. Termination.
-
-  You may not propagate or modify a covered work except as expressly
-provided under this License.  Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
-  However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
-  Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-  Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License.  If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
-  9. Acceptance Not Required for Having Copies.
-
-  You are not required to accept this License in order to receive or
-run a copy of the Program.  Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance.  However,
-nothing other than this License grants you permission to propagate or
-modify any covered work.  These actions infringe copyright if you do
-not accept this License.  Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
-  10. Automatic Licensing of Downstream Recipients.
-
-  Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License.  You are not responsible
-for enforcing compliance by third parties with this License.
-
-  An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations.  If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
-  You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License.  For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
-  11. Patents.
-
-  A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based.  The
-work thus licensed is called the contributor's "contributor version".
-
-  A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version.  For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
-  Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
-  In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement).  To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
-  If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients.  "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
-  If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
-  A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License.  You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
-  Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
-  12. No Surrender of Others' Freedom.
-
-  If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all.  For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
-  13. Use with the GNU Affero General Public License.
-
-  Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work.  The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
-  14. Revised Versions of this License.
-
-  The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-  Each version is given a distinguishing version number.  If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation.  If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
-  If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
-  Later license versions may give you additional or different
-permissions.  However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
-  15. Disclaimer of Warranty.
-
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. Limitation of Liability.
-
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
-  17. Interpretation of Sections 15 and 16.
-
-  If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    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 3 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, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
-  If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
-    <program>  Copyright (C) <year>  <name of author>
-    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
-  You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
-
-  The GNU General Public License does not permit incorporating your program
-into proprietary programs.  If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.  But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
Index: sc/buchla.supp
===================================================================
--- misc/buchla.supp	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,105 +1,0 @@
-{
-	_dl_*
-	Memcheck:Leak
-	...
-	fun:_dl_*
-}
-
-{
-	_XOpenLC
-	Memcheck:Leak
-	...
-	fun:_XOpenLC
-}
-
-{
-	X11_ShowCursor
-	Memcheck:Leak
-	...
-	fun:X11_ShowCursor
-}
-
-{
-	SDL_Init_REAL
-	Memcheck:Leak
-	...
-	fun:SDL_Init_REAL
-}
-
-{
-	libasound.so.*
-	Memcheck:Leak
-	...
-	obj:/usr/lib/x86_64-linux-gnu/libasound.so.*
-}
-
-{
-	libpulse.so.*
-	Memcheck:Leak
-	...
-	obj:/usr/lib/x86_64-linux-gnu/libpulse.so.*
-}
-
-{
-	X11_CreateWindow
-	Memcheck:Param
-	writev(vector[...])
-	...
-	fun:X11_CreateWindow
-}
-
-{
-	SDL_Quit_REAL
-	Memcheck:Overlap
-	...
-	fun:SDL_Quit_REAL
-}
-
-{
-	X11_GL_LoadLibrary
-	Memcheck:Addr4
-	...
-	fun:X11_GL_LoadLibrary
-}
-
-{
-	GL_*
-	Memcheck:Addr1
-	...
-	fun:GL_*
-}
-
-{
-	GL_*
-	Memcheck:Addr2
-	...
-	fun:GL_*
-}
-
-{
-	GL_*
-	Memcheck:Addr4
-	...
-	fun:GL_*
-}
-
-{
-	GL_*
-	Memcheck:Addr8
-	...
-	fun:GL_*
-}
-
-{
-	i965_dri.so
-	Memcheck:Addr2
-	...
-	obj:/usr/lib/x86_64-linux-gnu/dri/i965_dri.so
-}
-
-{
-	i965_dri.so
-	Memcheck:Addr4
-	...
-	obj:/usr/lib/x86_64-linux-gnu/dri/i965_dri.so
-}
Index: ck.sh
===================================================================
--- pack.sh	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,33 +1,0 @@
-#!/bin/bash
-
-VER=0.1
-
-NAME=buchla-${VER}
-DIR=/tmp/${NAME}
-
-OS=$(uname)
-
-rm -rf ${DIR}
-mkdir ${DIR}
-
-function copy()
-{
-	if [ -e ${1} ]; then
-		cp ${1} ${DIR}
-	else
-		echo "missing ${1} file" >&2
-		exit 1
-	fi
-}
-
-copy buchla-os-x
-copy buchla-linux
-copy buchla-win.exe
-
-copy vera.ttf
-copy bios.abs
-copy midas.abs
-copy buchla.disk
-
-(cd /tmp; zip -r ${NAME}.zip ${NAME})
-mv ${DIR}.zip .
Index: adme.txt
===================================================================
--- readme.txt	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,381 +1,0 @@
-Buchla 700 Hardware Emulator
-----------------------------
-
-This repository, buchla-emu.git, contains a software emulation of the
-Buchla 700's hardware.
-
-It is minimalistic; it emulates just enough of the hardware to be able
-to run the firmware from the companion repository, buchla-68k.git.
-
-We don't have access to original hardware, so this is our best guess
-based on the firmware source code published by Lynx Crowe - the
-firmware's developer - via Aaron Lanterman:
-
-  http://lanterman.ece.gatech.edu/buchla700/
-
-See the buchla-68k.git repository for the firmware source code.
-
-
-Building the emulator
----------------------
-
-The emulator uses SDL2, an abstraction layer for low-level machine
-access on Linux, OS X, and Windows. It can be obtained from the
-project's website:
-
-  https://libsdl.org/
-
-The SDL2 website also hosts the SDL2_net and SDL2_ttf projects, which
-add support for networking and TrueType fonts to SDL2
-
-SDL2_ttf, in turn, requires the FreeType library, which is available
-from the FreeType website:
-
-  https://www.freetype.org/
-
-Currently, we build the emulator natively on Linux and OS X. The
-Windows version is cross-compiled on Linux using a x86_64-w64-mingw32
-cross-toolchain.
-
-For Linux and OS X, our Makefile expects all of the above libraries to
-reside in /opt/sdl2. This is how we typically install them:
-
-  # Build and install FreeType first
-
-  tar zxvf freetype-2.7.1.tar.gz
-  cd freetype-2.7.1
-  mkdir build
-  cd build
-
-  # Skip the optional features (compressed fonts, etc.) that would
-  # create more dependencies
-
-  ../configure --prefix=/opt/sdl2 \
-    --without-zlib --without-bzip2 --without-png --without-harfbuzz
-
-  make
-  make install
-
-  # Then build and install SDL2
-
-  tar zxvf SDL2-2.0.5.tar.gz
-  cd SDL2-2.0.5
-  mkdir build
-  cd build
-
-  ../configure --prefix=/opt/sdl2
-
-  make
-  make install
-
-  # Build and install SDL2_ttf, now that we have FreeType and SDL2
-
-  tar zxvf SDL2_ttf-2.0.14.tar.gz
-  cd SDL2_ttf-2.0.14
-  mkdir build
-  cd build
-
-  ../configure --prefix=/opt/sdl2 \
-    --with-sdl-prefix=/opt/sdl2 --with-freetype-prefix=/opt/sdl2
-
-  make
-  make install
-
-  # Build and install SDL2_net last
-
-  tar zxvf SDL2_net-2.0.1.tar.gz
-  cd SDL2_net-2.0.1
-  mkdir build
-  cd build
-
-  ../configure --prefix=/opt/sdl2 --with-sdl-prefix=/opt/sdl2
-
-  make
-  make install
-
-  # Build and install RtMidi
-
-  tar zxvf rtmidi-3.0.0.tar.gz
-  cd rtmidi-3.0.0
-  mkdir build
-  cd build
-
-  ../configure --prefix=/opt/rtmidi
-
-  make
-  make install
-
-Now that we have everything in place, invoke
-
-  make buchla
-
-from the top-level directory of this repository to build the emulator.
-
-The cross-build for Windows is done similarly, with the following
-differences when configuring the libraries:
-
-  * We use "--prefix=/opt/sdl2-win" instead of "--prefix=/opt/sdl2",
-    so that the Windows versions of the SDL2 libraries go to a
-    different directory. That's where our Makefile expects to find
-    them when cross-building.
-
-    Analogously, we use "--prefix=/opt/rtmidi-win" when building
-    RtMidi.
-
-  * We additionally specify "--host=x86_64-w64-mingw32" to enable
-    cross-compilation.
-
-Then, to cross-build the emulator, invoke
-
-  make buchla.exe WIN=1
-
-from the top-level directory of this repository. Defining the "WIN"
-variable selects the cross-toolchain and "/opt/sdl2-win" as the
-library directory.
-
-In addition to the emulator, we need to build the mkdisk utility,
-which we'll use to create a 720-KiB floppy disk image that can be read
-by the Buchla firmware.
-
-Building mkdisk works pretty much like building the emulator. On Linux
-and OS X, invoke
-
-  make mkdisk
-
-from the top-level directory of this repository. To cross-build the
-Windows version, invoke
-
-  make mkdisk.exe WIN=1
-
-instead.
-
-
-Running the emulator
---------------------
-
-This is where this repository, buchla-emu, meets its companion
-repository, buchla-68k. We assume that you built the following files
-according to the instructions in the buchla-68k repository:
-
-  bios.abs
-  midas.abs
-
-Please copy (or symlink) them into the top-level directory of this
-repository, buchla-emu.
-
-bios.abs contains the Buchla 700's BIOS code. The file is loaded by
-the emulator directly to emulate the BIOS PROM.
-
-midas.abs is the MIDAS VII software. Unlike the BIOS, which resides in
-a PROM, it is loaded from a floppy disk. To create this floppy disk,
-we need the mkdisk utility.
-
-mkdisk expects to be run from inside the directory that contains
-midas.abs and produces a disk image file, buchla.disk in the same
-directory. For example, on Linux:
-
-  ~/buchla-emu$ ls -l midas.abs
-  lrwxrwxrwx 1 emu emu 23 Jul 30 18:07 midas.abs -> ../buchla-68k/midas.abs
-  ~/buchla-emu$ ./mkdisk
-  ~/buchla-emu$ ls -l buchla.disk
-  -rw-r--r-- 1 emu emu 737280 Aug  6 09:44 buchla.disk
-
-Now we have everything in place to run the emulator. On Linux and OS X
-you can invoke it directly from the top-level directory of this
-repository:
-
-  ~/buchla-emu$ ./buchla
-
-If you prefer to install the emulator elsewhere, be sure to copy the
-following files:
-
-  buchla | buchla.exe     emulator executable (.exe for Windows)
-  vera.ttf                emulator font
-  bios.abs                BIOS code
-  buchla.disk             disk image
-
-This also applies to copying the cross-compiled Windows emulator to a
-Windows machine.
-
-If you would like to keep the BIOS code, disk image, and font separate
-from the emulator executable, check out the emulator's -b, -d, and -f
-command line options. Use -h for an overview of all available options.
-
-
-Cross-debugging the firmware
-----------------------------
-
-While the emulator is running, it listens on TCP port 12053 for
-incoming connections from a GDB cross-debugger. This allows for
-comfortable source-level debugging of the cross-compiled BIOS and
-MIDAS VII code, while it runs in the emulator.
-
-We assume that you have a GCC cross-toolchain in /opt/cross-m68k, as
-described in the buchla-68k repository. Based on that, we build a
-GDB cross-debugger:
-
-  # If you haven't yet done so, add the cross-toolchain to your
-  # PATH, so that the GDB build can find it.
-
-  export PATH="/opt/cross-m68k/bin:${PATH}"
-
-  tar zxvf gdb-7.12.tar.gz
-  cd gdb-7.12
-
-  mkdir build
-  cd build
-
-  ../configure --prefix=/opt/cross-m68k --target=m68k-none-elf
-
-  make -j2
-  make install
-
-The Buchla firmware uses its own (Atari-like) object and executable
-file format. However, the cross-toolchain and the cross-debugger
-support the ELF standard.
-
-When you built the BIOS and MIDAS VII software, you ended up with two
-files in the Buchla's executable file format, bios.abs and midas.abs.
-However, the cross-build process also produces matching ELF files,
-bios.elf and midas.elf, suitable for the cross-debugger.
-
-Depending on whether you would like to cross-debug the BIOS or MIDAS
-VII, you'd specify either bios.elf or midas.elf when invoking the
-cross-debugger.
-
-To follow along the following example, copy (or symlink) bios.elf and
-midas.elf from the buchla-68k repository into the top-level directory
-of this repository.
-
-In order to open a debug session for the BIOS, run the cross-debugger
-with bios.abs and connect it to the running emulator using GDB's
-
-  target remote :12053
-
-command. 12053 is the port on which the emulator listens for incoming
-GDB connections.
-
-  host:~/buchla-emu$ m68k-none-elf-gdb ./bios.elf
-  GNU gdb (GDB) 7.12
-  Copyright (C) 2016 Free Software Foundation, Inc.
-  [...]
-  (gdb) target remote :12053
-  Remote debugging using :12053
-  trwzsup () at rom/bios.s:832
-  832           move.l  0(a0,d0),d0     | Get routine address
-  (gdb)
-
-From here on, everything is pretty much standard GDB, for example:
-
-  (gdb) break pscan
-  Breakpoint 1 at 0x105a64: file rom/romp.c, line 3403.
-  (gdb) cont
-  [...]
-  (gdb) bt
-  #0  pscan () at rom/romp.c:3403
-  #1  0x00105e96 in main () at rom/romp.c:3587
-  #2  0x00105fd6 in Croot (cp=0x0) at prolog/croot.c:141
-  #3  0x00105f52 in start1 () at prolog/fsmain.s:59
-  (gdb)
-
-In order to debug MIDAS VII, run the cross-debugger with midas.elf,
-instead:
-
-  host:~/buchla-emu$ m68k-none-elf-gdb ./midas.elf
-  GNU gdb (GDB) 7.12
-  Copyright (C) 2016 Free Software Foundation, Inc.
-  [...]
-
-
-Emulated hardware
------------------
-
-Here's what we currently emulate:
-
-  * Motorola 68000 CPU. This is actually the Musashi CPU emulator by
-    Karl Stenerud:
-
-      https://github.com/kstenerud/Musashi
-
-  * Intel 82716: Video chip.
-
-  * Epson SED1335: LCD controller.
-
-  * Western Digital WD1772: Floppy disk controller.
-
-  * Rockwell R65C52: Serial console and MIDI ports.
-
-  * Motorola MC6840: Timers.
-
-  * Unknown item #1: A program running on a microcontroller. It
-    converts the analog signals from the Buchla's controller pads to
-    digital values.
-
-    Neither the program, nor the microcontroller are known, but the
-    protocol (known from the firmware source code) is pretty simple
-    and self-explanatory.
-
-The next development milestone will hopefully emulate the following
-additional components:
-
-  * National Semiconductor LMC835: Equalizer.
-
-  * General Instrument AY-3-8910: A sound chip, which is not used for
-    sound generation, but only for its I/O ports. It connects the CPU
-    to the above equalizer chip.
-
-  * A few indicator LEDs.
-
-  * Unknown item #2: The actual sound generator, referred to by the
-    firmware source code as "the FPU." This is the biggest unknown so
-    far. Judging from the firmware source code it consist of two
-    parts:
-
-      1. The function generator that generates the 15 different
-         parameter envelopes for each of the 12 voices:
-
-           - 4x FM modulator (oscillator) frequency.
-
-           - 6x FM modulator (oscillator) envelope.
-
-           - 1x Output signal amplitude envelope.
-
-           - 1x Output signal filter envelope.
-
-           - 1x Output signal filter resonance envelope.
-
-           - 1x Output signal stereo location.
-
-           - 1x "Dynamics" - whatever that is.
-
-         The firmware feeds the the points of the envelopes drawn in
-         the MIDAS VII instrument editor to the function generator,
-         which then interpolates between them.
-
-      2. The digital oscillator.
-
-         XXX - Details to be filled in.
-
-         We don't know how many of the envelopes not related to FM
-         (e.g., the filter) are actually used digitally. At least some
-         of the envelopes probably control analog circuits.
-
-    This "two FPU parts" hypothesis would be in line with the "four
-    computers" marketing claim from the Buchla 700 marketing copy. The
-    four "computers" would be the Motorola 68000, the microcontroller
-    that does the A/D conversion of the pad inputs, plus the two parts
-    that constitute "the FPU."
-
-    The firmware source code archive indicates that the FPU is based
-    on micro-programmable hardware. We recently ran this by Lynx, the
-    developer of the firmware, who generously agreed to meet up with
-    us in Oakland, CA. While he did not work on the FPU and thus was
-    not familiar with its implementation details, he was able to
-    confirm that the FPU is based on AMD's Am2900 family.
-
-If you have access to an actual Buchla 700, please do contact us. It
-would be great to be able to compare the emulation to real hardware.
-
-If your Buchla is non-functional, this is also fine. We might be able
-to gain some insights from reading out the FPU microcode PROMs or from
-figuring out how the FPU chips are wired together.
Index: tup
===================================================================
--- setup	(revision 3153af3ee9bb948ed271c84ab58f365f2f338090)
+++ 	(revision )
@@ -1,1 +1,0 @@
-export PATH="/opt/cross-m68k/bin:${PATH}"
