Added stuff.
parent
383396b35c
commit
1734741725
|
|
@ -0,0 +1 @@
|
||||||
|
/.metadata/
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="optional" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="test" value="true"/>
|
||||||
|
<attribute name="optional" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="test" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="output" path="target/classes"/>
|
||||||
|
</classpath>
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
/target/
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>playing-coffee</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.release=disabled
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.8
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
activeProfiles=
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
resolveWorkspaceProjects=true
|
||||||
|
version=1
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,646 @@
|
||||||
|
[19:39:15.741] Info: Initialized logger
|
||||||
|
[19:39:15.830] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:15.831] Info: Pushing 0x 4ce to the stack.
|
||||||
|
[19:39:15.832] Info: Pushing 0x 39d to the stack.
|
||||||
|
[19:39:15.832] Info: Pushing 0x 23a to the stack.
|
||||||
|
[19:39:15.832] Info: Pushing 0x 175 to the stack.
|
||||||
|
[19:39:15.832] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:15.832] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:15.833] Info: Pushing 0x 4eb to the stack.
|
||||||
|
[19:39:15.833] Info: Pushing 0x 3d7 to the stack.
|
||||||
|
[19:39:15.833] Info: Pushing 0x 2af to the stack.
|
||||||
|
[19:39:15.833] Info: Pushing 0x 15e to the stack.
|
||||||
|
[19:39:15.833] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:15.834] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:15.834] Info: Pushing 0x 4ed to the stack.
|
||||||
|
[19:39:15.834] Info: Pushing 0x 3db to the stack.
|
||||||
|
[19:39:15.834] Info: Pushing 0x 2b7 to the stack.
|
||||||
|
[19:39:15.835] Info: Pushing 0x 16f to the stack.
|
||||||
|
[19:39:15.835] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:15.835] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:15.835] Info: Pushing 0x 4de to the stack.
|
||||||
|
[19:39:15.835] Info: Pushing 0x 3bd to the stack.
|
||||||
|
[19:39:15.835] Info: Pushing 0x 27b to the stack.
|
||||||
|
[19:39:15.835] Info: Pushing 0x 1f7 to the stack.
|
||||||
|
[19:39:15.835] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:15.836] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:15.836] Info: Pushing 0x 466 to the stack.
|
||||||
|
[19:39:15.836] Info: Pushing 0x 3cc to the stack.
|
||||||
|
[19:39:15.836] Info: Pushing 0x 299 to the stack.
|
||||||
|
[19:39:15.836] Info: Pushing 0x 132 to the stack.
|
||||||
|
[19:39:15.836] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:15.836] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:15.836] Info: Pushing 0x 465 to the stack.
|
||||||
|
[19:39:15.836] Info: Pushing 0x 3ca to the stack.
|
||||||
|
[19:39:15.837] Info: Pushing 0x 295 to the stack.
|
||||||
|
[19:39:15.837] Info: Pushing 0x 12b to the stack.
|
||||||
|
[19:39:15.837] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:15.837] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:15.837] Info: Pushing 0x 466 to the stack.
|
||||||
|
[19:39:15.837] Info: Pushing 0x 3cc to the stack.
|
||||||
|
[19:39:15.837] Info: Pushing 0x 299 to the stack.
|
||||||
|
[19:39:15.837] Info: Pushing 0x 132 to the stack.
|
||||||
|
[19:39:15.838] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:15.838] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:15.838] Info: Pushing 0x 465 to the stack.
|
||||||
|
[19:39:15.838] Info: Pushing 0x 3ca to the stack.
|
||||||
|
[19:39:15.838] Info: Pushing 0x 295 to the stack.
|
||||||
|
[19:39:15.838] Info: Pushing 0x 12b to the stack.
|
||||||
|
[19:39:15.838] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:15.838] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:15.839] Info: Pushing 0x 4cc to the stack.
|
||||||
|
[19:39:15.839] Info: Pushing 0x 399 to the stack.
|
||||||
|
[19:39:15.839] Info: Pushing 0x 232 to the stack.
|
||||||
|
[19:39:15.839] Info: Pushing 0x 165 to the stack.
|
||||||
|
[19:39:15.839] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:15.839] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:15.839] Info: Pushing 0x 4ca to the stack.
|
||||||
|
[19:39:15.839] Info: Pushing 0x 395 to the stack.
|
||||||
|
[19:39:15.840] Info: Pushing 0x 22b to the stack.
|
||||||
|
[19:39:15.840] Info: Pushing 0x 156 to the stack.
|
||||||
|
[19:39:15.840] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:15.840] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:15.840] Info: Pushing 0x 40d to the stack.
|
||||||
|
[19:39:15.840] Info: Pushing 0x 31a to the stack.
|
||||||
|
[19:39:15.840] Info: Pushing 0x 234 to the stack.
|
||||||
|
[19:39:15.840] Info: Pushing 0x 169 to the stack.
|
||||||
|
[19:39:15.841] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:15.841] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:15.841] Info: Pushing 0x 4d2 to the stack.
|
||||||
|
[19:39:15.841] Info: Pushing 0x 3a4 to the stack.
|
||||||
|
[19:39:15.841] Info: Pushing 0x 248 to the stack.
|
||||||
|
[19:39:15.841] Info: Pushing 0x 190 to the stack.
|
||||||
|
[19:39:15.841] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:15.841] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:15.841] Info: Pushing 0x 400 to the stack.
|
||||||
|
[19:39:15.842] Info: Pushing 0x 300 to the stack.
|
||||||
|
[19:39:15.842] Info: Pushing 0x 200 to the stack.
|
||||||
|
[19:39:15.842] Info: Pushing 0x 100 to the stack.
|
||||||
|
[19:39:15.842] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:15.842] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:15.842] Info: Pushing 0x 400 to the stack.
|
||||||
|
[19:39:17.652] Info: Pushing 0x 300 to the stack.
|
||||||
|
[19:39:17.652] Info: Pushing 0x 200 to the stack.
|
||||||
|
[19:39:17.652] Info: Pushing 0x 100 to the stack.
|
||||||
|
[19:39:17.652] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.652] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.652] Info: Pushing 0x 40b to the stack.
|
||||||
|
[19:39:17.652] Info: Pushing 0x 316 to the stack.
|
||||||
|
[19:39:17.653] Info: Pushing 0x 22c to the stack.
|
||||||
|
[19:39:17.653] Info: Pushing 0x 159 to the stack.
|
||||||
|
[19:39:17.653] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.653] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.653] Info: Pushing 0x 4b3 to the stack.
|
||||||
|
[19:39:17.653] Info: Pushing 0x 366 to the stack.
|
||||||
|
[19:39:17.653] Info: Pushing 0x 2cc to the stack.
|
||||||
|
[19:39:17.653] Info: Pushing 0x 198 to the stack.
|
||||||
|
[19:39:17.653] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.654] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.654] Info: Pushing 0x 403 to the stack.
|
||||||
|
[19:39:17.654] Info: Pushing 0x 306 to the stack.
|
||||||
|
[19:39:17.654] Info: Pushing 0x 20c to the stack.
|
||||||
|
[19:39:17.654] Info: Pushing 0x 118 to the stack.
|
||||||
|
[19:39:17.654] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.654] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.654] Info: Pushing 0x 431 to the stack.
|
||||||
|
[19:39:17.655] Info: Pushing 0x 362 to the stack.
|
||||||
|
[19:39:17.655] Info: Pushing 0x 2c4 to the stack.
|
||||||
|
[19:39:17.655] Info: Pushing 0x 188 to the stack.
|
||||||
|
[19:39:17.655] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.655] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.655] Info: Pushing 0x 473 to the stack.
|
||||||
|
[19:39:17.655] Info: Pushing 0x 3e6 to the stack.
|
||||||
|
[19:39:17.655] Info: Pushing 0x 2cd to the stack.
|
||||||
|
[19:39:17.655] Info: Pushing 0x 19a to the stack.
|
||||||
|
[19:39:17.655] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.655] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.656] Info: Pushing 0x 435 to the stack.
|
||||||
|
[19:39:17.656] Info: Pushing 0x 36a to the stack.
|
||||||
|
[19:39:17.656] Info: Pushing 0x 2d5 to the stack.
|
||||||
|
[19:39:17.656] Info: Pushing 0x 1ab to the stack.
|
||||||
|
[19:39:17.656] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.656] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.656] Info: Pushing 0x 400 to the stack.
|
||||||
|
[19:39:17.657] Info: Pushing 0x 300 to the stack.
|
||||||
|
[19:39:17.657] Info: Pushing 0x 200 to the stack.
|
||||||
|
[19:39:17.657] Info: Pushing 0x 100 to the stack.
|
||||||
|
[19:39:17.657] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.658] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.658] Info: Pushing 0x 400 to the stack.
|
||||||
|
[19:39:17.658] Info: Pushing 0x 300 to the stack.
|
||||||
|
[19:39:17.658] Info: Pushing 0x 200 to the stack.
|
||||||
|
[19:39:17.658] Info: Pushing 0x 100 to the stack.
|
||||||
|
[19:39:17.658] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.658] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.658] Info: Pushing 0x 483 to the stack.
|
||||||
|
[19:39:17.658] Info: Pushing 0x 307 to the stack.
|
||||||
|
[19:39:17.658] Info: Pushing 0x 20e to the stack.
|
||||||
|
[19:39:17.660] Info: Pushing 0x 11c to the stack.
|
||||||
|
[19:39:17.660] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.660] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.660] Info: Pushing 0x 439 to the stack.
|
||||||
|
[19:39:17.667] Info: Pushing 0x 373 to the stack.
|
||||||
|
[19:39:17.668] Info: Pushing 0x 2e6 to the stack.
|
||||||
|
[19:39:17.668] Info: Pushing 0x 1cc to the stack.
|
||||||
|
[19:39:17.668] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.668] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.668] Info: Pushing 0x 400 to the stack.
|
||||||
|
[19:39:17.668] Info: Pushing 0x 300 to the stack.
|
||||||
|
[19:39:17.668] Info: Pushing 0x 200 to the stack.
|
||||||
|
[19:39:17.668] Info: Pushing 0x 100 to the stack.
|
||||||
|
[19:39:17.668] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.668] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.668] Info: Pushing 0x 400 to the stack.
|
||||||
|
[19:39:17.669] Info: Pushing 0x 300 to the stack.
|
||||||
|
[19:39:17.669] Info: Pushing 0x 200 to the stack.
|
||||||
|
[19:39:17.669] Info: Pushing 0x 100 to the stack.
|
||||||
|
[19:39:17.669] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.669] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.669] Info: Pushing 0x 40c to the stack.
|
||||||
|
[19:39:17.669] Info: Pushing 0x 318 to the stack.
|
||||||
|
[19:39:17.669] Info: Pushing 0x 230 to the stack.
|
||||||
|
[19:39:17.669] Info: Pushing 0x 161 to the stack.
|
||||||
|
[19:39:17.669] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.670] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.670] Info: Pushing 0x 4c2 to the stack.
|
||||||
|
[19:39:17.670] Info: Pushing 0x 384 to the stack.
|
||||||
|
[19:39:17.670] Info: Pushing 0x 208 to the stack.
|
||||||
|
[19:39:17.670] Info: Pushing 0x 110 to the stack.
|
||||||
|
[19:39:17.670] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.670] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.670] Info: Pushing 0x 400 to the stack.
|
||||||
|
[19:39:17.670] Info: Pushing 0x 300 to the stack.
|
||||||
|
[19:39:17.670] Info: Pushing 0x 200 to the stack.
|
||||||
|
[19:39:17.670] Info: Pushing 0x 100 to the stack.
|
||||||
|
[19:39:17.671] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.671] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.671] Info: Pushing 0x 400 to the stack.
|
||||||
|
[19:39:17.671] Info: Pushing 0x 300 to the stack.
|
||||||
|
[19:39:17.671] Info: Pushing 0x 200 to the stack.
|
||||||
|
[19:39:17.671] Info: Pushing 0x 100 to the stack.
|
||||||
|
[19:39:17.671] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.671] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.671] Info: Pushing 0x 40d to the stack.
|
||||||
|
[19:39:17.671] Info: Pushing 0x 31a to the stack.
|
||||||
|
[19:39:17.671] Info: Pushing 0x 234 to the stack.
|
||||||
|
[19:39:17.671] Info: Pushing 0x 169 to the stack.
|
||||||
|
[19:39:17.671] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.671] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.672] Info: Pushing 0x 4d2 to the stack.
|
||||||
|
[19:39:17.672] Info: Pushing 0x 3a4 to the stack.
|
||||||
|
[19:39:17.672] Info: Pushing 0x 248 to the stack.
|
||||||
|
[19:39:17.672] Info: Pushing 0x 190 to the stack.
|
||||||
|
[19:39:17.672] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.672] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.672] Info: Pushing 0x 400 to the stack.
|
||||||
|
[19:39:17.672] Info: Pushing 0x 300 to the stack.
|
||||||
|
[19:39:17.672] Info: Pushing 0x 200 to the stack.
|
||||||
|
[19:39:17.672] Info: Pushing 0x 100 to the stack.
|
||||||
|
[19:39:17.672] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.672] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.673] Info: Pushing 0x 400 to the stack.
|
||||||
|
[19:39:17.673] Info: Pushing 0x 300 to the stack.
|
||||||
|
[19:39:17.673] Info: Pushing 0x 200 to the stack.
|
||||||
|
[19:39:17.673] Info: Pushing 0x 100 to the stack.
|
||||||
|
[19:39:17.673] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.673] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.673] Info: Pushing 0x 408 to the stack.
|
||||||
|
[19:39:17.673] Info: Pushing 0x 310 to the stack.
|
||||||
|
[19:39:17.673] Info: Pushing 0x 220 to the stack.
|
||||||
|
[19:39:17.673] Info: Pushing 0x 141 to the stack.
|
||||||
|
[19:39:17.673] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.673] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.673] Info: Pushing 0x 482 to the stack.
|
||||||
|
[19:39:17.673] Info: Pushing 0x 304 to the stack.
|
||||||
|
[19:39:17.674] Info: Pushing 0x 208 to the stack.
|
||||||
|
[19:39:17.674] Info: Pushing 0x 110 to the stack.
|
||||||
|
[19:39:17.674] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.674] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.674] Info: Pushing 0x 411 to the stack.
|
||||||
|
[19:39:17.674] Info: Pushing 0x 322 to the stack.
|
||||||
|
[19:39:17.674] Info: Pushing 0x 244 to the stack.
|
||||||
|
[19:39:17.674] Info: Pushing 0x 188 to the stack.
|
||||||
|
[19:39:17.674] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.674] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.674] Info: Pushing 0x 410 to the stack.
|
||||||
|
[19:39:17.675] Info: Pushing 0x 320 to the stack.
|
||||||
|
[19:39:17.675] Info: Pushing 0x 240 to the stack.
|
||||||
|
[19:39:17.675] Info: Pushing 0x 180 to the stack.
|
||||||
|
[19:39:17.675] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.675] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.675] Info: Pushing 0x 41f to the stack.
|
||||||
|
[19:39:17.675] Info: Pushing 0x 33e to the stack.
|
||||||
|
[19:39:17.675] Info: Pushing 0x 27c to the stack.
|
||||||
|
[19:39:17.675] Info: Pushing 0x 1f9 to the stack.
|
||||||
|
[19:39:17.675] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.675] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.675] Info: Pushing 0x 4f3 to the stack.
|
||||||
|
[19:39:17.675] Info: Pushing 0x 3e6 to the stack.
|
||||||
|
[19:39:17.676] Info: Pushing 0x 2cc to the stack.
|
||||||
|
[19:39:17.676] Info: Pushing 0x 198 to the stack.
|
||||||
|
[19:39:17.676] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.676] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.676] Info: Pushing 0x 488 to the stack.
|
||||||
|
[19:39:17.676] Info: Pushing 0x 311 to the stack.
|
||||||
|
[19:39:17.676] Info: Pushing 0x 222 to the stack.
|
||||||
|
[19:39:17.676] Info: Pushing 0x 145 to the stack.
|
||||||
|
[19:39:17.676] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.676] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.676] Info: Pushing 0x 48a to the stack.
|
||||||
|
[19:39:17.676] Info: Pushing 0x 315 to the stack.
|
||||||
|
[19:39:17.676] Info: Pushing 0x 22a to the stack.
|
||||||
|
[19:39:17.677] Info: Pushing 0x 154 to the stack.
|
||||||
|
[19:39:17.677] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.677] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.677] Info: Pushing 0x 489 to the stack.
|
||||||
|
[19:39:17.677] Info: Pushing 0x 313 to the stack.
|
||||||
|
[19:39:17.677] Info: Pushing 0x 226 to the stack.
|
||||||
|
[19:39:17.677] Info: Pushing 0x 14d to the stack.
|
||||||
|
[19:39:17.677] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.677] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.677] Info: Pushing 0x 49a to the stack.
|
||||||
|
[19:39:17.678] Info: Pushing 0x 335 to the stack.
|
||||||
|
[19:39:17.678] Info: Pushing 0x 26a to the stack.
|
||||||
|
[19:39:17.678] Info: Pushing 0x 1d4 to the stack.
|
||||||
|
[19:39:17.678] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.678] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.678] Info: Pushing 0x 400 to the stack.
|
||||||
|
[19:39:17.678] Info: Pushing 0x 300 to the stack.
|
||||||
|
[19:39:17.678] Info: Pushing 0x 200 to the stack.
|
||||||
|
[19:39:17.678] Info: Pushing 0x 100 to the stack.
|
||||||
|
[19:39:17.678] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.678] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.678] Info: Pushing 0x 400 to the stack.
|
||||||
|
[19:39:17.678] Info: Pushing 0x 300 to the stack.
|
||||||
|
[19:39:17.678] Info: Pushing 0x 200 to the stack.
|
||||||
|
[19:39:17.680] Info: Pushing 0x 100 to the stack.
|
||||||
|
[19:39:17.680] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.680] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.680] Info: Pushing 0x 40e to the stack.
|
||||||
|
[19:39:17.680] Info: Pushing 0x 31c to the stack.
|
||||||
|
[19:39:17.680] Info: Pushing 0x 238 to the stack.
|
||||||
|
[19:39:17.680] Info: Pushing 0x 171 to the stack.
|
||||||
|
[19:39:17.680] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.680] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.681] Info: Pushing 0x 4e3 to the stack.
|
||||||
|
[19:39:17.681] Info: Pushing 0x 3c6 to the stack.
|
||||||
|
[19:39:17.681] Info: Pushing 0x 28c to the stack.
|
||||||
|
[19:39:17.681] Info: Pushing 0x 118 to the stack.
|
||||||
|
[19:39:17.681] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.681] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.681] Info: Pushing 0x 4dc to the stack.
|
||||||
|
[19:39:17.681] Info: Pushing 0x 3b9 to the stack.
|
||||||
|
[19:39:17.681] Info: Pushing 0x 272 to the stack.
|
||||||
|
[19:39:17.682] Info: Pushing 0x 1e5 to the stack.
|
||||||
|
[19:39:17.682] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.682] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.682] Info: Pushing 0x 4ca to the stack.
|
||||||
|
[19:39:17.682] Info: Pushing 0x 395 to the stack.
|
||||||
|
[19:39:17.682] Info: Pushing 0x 22b to the stack.
|
||||||
|
[19:39:17.682] Info: Pushing 0x 156 to the stack.
|
||||||
|
[19:39:17.682] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.682] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.682] Info: Pushing 0x 4cc to the stack.
|
||||||
|
[19:39:17.682] Info: Pushing 0x 399 to the stack.
|
||||||
|
[19:39:17.682] Info: Pushing 0x 232 to the stack.
|
||||||
|
[19:39:17.682] Info: Pushing 0x 165 to the stack.
|
||||||
|
[19:39:17.683] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.683] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.683] Info: Pushing 0x 4ca to the stack.
|
||||||
|
[19:39:17.683] Info: Pushing 0x 395 to the stack.
|
||||||
|
[19:39:17.683] Info: Pushing 0x 22b to the stack.
|
||||||
|
[19:39:17.683] Info: Pushing 0x 156 to the stack.
|
||||||
|
[19:39:17.683] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.683] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.683] Info: Pushing 0x 46e to the stack.
|
||||||
|
[19:39:17.683] Info: Pushing 0x 3dc to the stack.
|
||||||
|
[19:39:17.683] Info: Pushing 0x 2b9 to the stack.
|
||||||
|
[19:39:17.683] Info: Pushing 0x 173 to the stack.
|
||||||
|
[19:39:17.683] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.683] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.684] Info: Pushing 0x 4e7 to the stack.
|
||||||
|
[19:39:17.684] Info: Pushing 0x 3ce to the stack.
|
||||||
|
[19:39:17.684] Info: Pushing 0x 29d to the stack.
|
||||||
|
[19:39:17.684] Info: Pushing 0x 13b to the stack.
|
||||||
|
[19:39:17.684] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.684] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.684] Info: Pushing 0x 4e6 to the stack.
|
||||||
|
[19:39:17.684] Info: Pushing 0x 3cd to the stack.
|
||||||
|
[19:39:17.684] Info: Pushing 0x 29b to the stack.
|
||||||
|
[19:39:17.684] Info: Pushing 0x 136 to the stack.
|
||||||
|
[19:39:17.684] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.684] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.684] Info: Pushing 0x 46d to the stack.
|
||||||
|
[19:39:17.684] Info: Pushing 0x 3db to the stack.
|
||||||
|
[19:39:17.685] Info: Pushing 0x 2b7 to the stack.
|
||||||
|
[19:39:17.685] Info: Pushing 0x 16f to the stack.
|
||||||
|
[19:39:17.685] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.685] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.685] Info: Pushing 0x 4dd to the stack.
|
||||||
|
[19:39:17.685] Info: Pushing 0x 3bb to the stack.
|
||||||
|
[19:39:17.685] Info: Pushing 0x 276 to the stack.
|
||||||
|
[19:39:17.685] Info: Pushing 0x 1ed to the stack.
|
||||||
|
[19:39:17.686] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.686] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.686] Info: Pushing 0x 4da to the stack.
|
||||||
|
[19:39:17.686] Info: Pushing 0x 3b5 to the stack.
|
||||||
|
[19:39:17.686] Info: Pushing 0x 26b to the stack.
|
||||||
|
[19:39:17.686] Info: Pushing 0x 1d6 to the stack.
|
||||||
|
[19:39:17.686] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.686] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.686] Info: Pushing 0x 4dd to the stack.
|
||||||
|
[19:39:17.686] Info: Pushing 0x 3bb to the stack.
|
||||||
|
[19:39:17.686] Info: Pushing 0x 276 to the stack.
|
||||||
|
[19:39:17.686] Info: Pushing 0x 1ed to the stack.
|
||||||
|
[19:39:17.686] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.686] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.688] Info: Pushing 0x 4da to the stack.
|
||||||
|
[19:39:17.688] Info: Pushing 0x 3b5 to the stack.
|
||||||
|
[19:39:17.688] Info: Pushing 0x 26b to the stack.
|
||||||
|
[19:39:17.688] Info: Pushing 0x 1d6 to the stack.
|
||||||
|
[19:39:17.689] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.689] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.689] Info: Pushing 0x 4d9 to the stack.
|
||||||
|
[19:39:17.689] Info: Pushing 0x 3b3 to the stack.
|
||||||
|
[19:39:17.689] Info: Pushing 0x 266 to the stack.
|
||||||
|
[19:39:17.689] Info: Pushing 0x 1cd to the stack.
|
||||||
|
[19:39:17.689] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.689] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.689] Info: Pushing 0x 49a to the stack.
|
||||||
|
[19:39:17.689] Info: Pushing 0x 335 to the stack.
|
||||||
|
[19:39:17.689] Info: Pushing 0x 26b to the stack.
|
||||||
|
[19:39:17.689] Info: Pushing 0x 1d6 to the stack.
|
||||||
|
[19:39:17.689] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.689] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.689] Info: Pushing 0x 499 to the stack.
|
||||||
|
[19:39:17.689] Info: Pushing 0x 333 to the stack.
|
||||||
|
[19:39:17.689] Info: Pushing 0x 266 to the stack.
|
||||||
|
[19:39:17.690] Info: Pushing 0x 1cd to the stack.
|
||||||
|
[19:39:17.690] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.690] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.690] Info: Pushing 0x 49a to the stack.
|
||||||
|
[19:39:17.690] Info: Pushing 0x 335 to the stack.
|
||||||
|
[19:39:17.690] Info: Pushing 0x 26a to the stack.
|
||||||
|
[19:39:17.690] Info: Pushing 0x 1d4 to the stack.
|
||||||
|
[19:39:17.690] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.690] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.690] Info: Pushing 0x 4bb to the stack.
|
||||||
|
[19:39:17.690] Info: Pushing 0x 377 to the stack.
|
||||||
|
[19:39:17.690] Info: Pushing 0x 2ef to the stack.
|
||||||
|
[19:39:17.690] Info: Pushing 0x 1df to the stack.
|
||||||
|
[19:39:17.690] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.690] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.690] Info: Pushing 0x 4bf to the stack.
|
||||||
|
[19:39:17.691] Info: Pushing 0x 37f to the stack.
|
||||||
|
[19:39:17.691] Info: Pushing 0x 2fe to the stack.
|
||||||
|
[19:39:17.691] Info: Pushing 0x 1fd to the stack.
|
||||||
|
[19:39:17.691] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.691] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.691] Info: Pushing 0x 4bb to the stack.
|
||||||
|
[19:39:17.691] Info: Pushing 0x 377 to the stack.
|
||||||
|
[19:39:17.691] Info: Pushing 0x 2ef to the stack.
|
||||||
|
[19:39:17.691] Info: Pushing 0x 1df to the stack.
|
||||||
|
[19:39:17.691] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.691] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.691] Info: Pushing 0x 4bf to the stack.
|
||||||
|
[19:39:17.691] Info: Pushing 0x 37f to the stack.
|
||||||
|
[19:39:17.691] Info: Pushing 0x 2fe to the stack.
|
||||||
|
[19:39:17.691] Info: Pushing 0x 1fd to the stack.
|
||||||
|
[19:39:17.691] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.691] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.691] Info: Pushing 0x 467 to the stack.
|
||||||
|
[19:39:17.692] Info: Pushing 0x 3ce to the stack.
|
||||||
|
[19:39:17.692] Info: Pushing 0x 29d to the stack.
|
||||||
|
[19:39:17.694] Info: Pushing 0x 13a to the stack.
|
||||||
|
[19:39:17.694] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.694] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.694] Info: Pushing 0x 475 to the stack.
|
||||||
|
[19:39:17.694] Info: Pushing 0x 3ea to the stack.
|
||||||
|
[19:39:17.694] Info: Pushing 0x 2d5 to the stack.
|
||||||
|
[19:39:17.694] Info: Pushing 0x 1ab to the stack.
|
||||||
|
[19:39:17.694] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.694] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.694] Info: Pushing 0x 463 to the stack.
|
||||||
|
[19:39:17.694] Info: Pushing 0x 3c6 to the stack.
|
||||||
|
[19:39:17.694] Info: Pushing 0x 28d to the stack.
|
||||||
|
[19:39:17.694] Info: Pushing 0x 11a to the stack.
|
||||||
|
[19:39:17.694] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.694] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.694] Info: Pushing 0x 435 to the stack.
|
||||||
|
[19:39:17.694] Info: Pushing 0x 36a to the stack.
|
||||||
|
[19:39:17.694] Info: Pushing 0x 2d5 to the stack.
|
||||||
|
[19:39:17.695] Info: Pushing 0x 1ab to the stack.
|
||||||
|
[19:39:17.695] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.695] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.695] Info: Pushing 0x 46e to the stack.
|
||||||
|
[19:39:17.695] Info: Pushing 0x 3dc to the stack.
|
||||||
|
[19:39:17.695] Info: Pushing 0x 2b9 to the stack.
|
||||||
|
[19:39:17.695] Info: Pushing 0x 173 to the stack.
|
||||||
|
[19:39:17.695] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.695] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.695] Info: Pushing 0x 4e7 to the stack.
|
||||||
|
[19:39:17.695] Info: Pushing 0x 3ce to the stack.
|
||||||
|
[19:39:17.695] Info: Pushing 0x 29d to the stack.
|
||||||
|
[19:39:17.695] Info: Pushing 0x 13b to the stack.
|
||||||
|
[19:39:17.695] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.696] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.696] Info: Pushing 0x 40e to the stack.
|
||||||
|
[19:39:17.696] Info: Pushing 0x 31c to the stack.
|
||||||
|
[19:39:17.696] Info: Pushing 0x 238 to the stack.
|
||||||
|
[19:39:17.696] Info: Pushing 0x 171 to the stack.
|
||||||
|
[19:39:17.696] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.696] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.696] Info: Pushing 0x 4e3 to the stack.
|
||||||
|
[19:39:17.696] Info: Pushing 0x 3c6 to the stack.
|
||||||
|
[19:39:17.696] Info: Pushing 0x 28c to the stack.
|
||||||
|
[19:39:17.696] Info: Pushing 0x 118 to the stack.
|
||||||
|
[19:39:17.696] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.696] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.696] Info: Pushing 0x 4ec to the stack.
|
||||||
|
[19:39:17.696] Info: Pushing 0x 3d9 to the stack.
|
||||||
|
[19:39:17.696] Info: Pushing 0x 2b3 to the stack.
|
||||||
|
[19:39:17.696] Info: Pushing 0x 167 to the stack.
|
||||||
|
[19:39:17.696] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.696] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.696] Info: Pushing 0x 4ce to the stack.
|
||||||
|
[19:39:17.697] Info: Pushing 0x 39d to the stack.
|
||||||
|
[19:39:17.697] Info: Pushing 0x 23b to the stack.
|
||||||
|
[19:39:17.697] Info: Pushing 0x 177 to the stack.
|
||||||
|
[19:39:17.697] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.697] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.698] Info: Pushing 0x 4cc to the stack.
|
||||||
|
[19:39:17.698] Info: Pushing 0x 399 to the stack.
|
||||||
|
[19:39:17.698] Info: Pushing 0x 232 to the stack.
|
||||||
|
[19:39:17.698] Info: Pushing 0x 165 to the stack.
|
||||||
|
[19:39:17.698] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.698] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.698] Info: Pushing 0x 4ca to the stack.
|
||||||
|
[19:39:17.698] Info: Pushing 0x 395 to the stack.
|
||||||
|
[19:39:17.698] Info: Pushing 0x 22b to the stack.
|
||||||
|
[19:39:17.698] Info: Pushing 0x 156 to the stack.
|
||||||
|
[19:39:17.699] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.699] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.699] Info: Pushing 0x 4dd to the stack.
|
||||||
|
[19:39:17.699] Info: Pushing 0x 3bb to the stack.
|
||||||
|
[19:39:17.699] Info: Pushing 0x 276 to the stack.
|
||||||
|
[19:39:17.699] Info: Pushing 0x 1ed to the stack.
|
||||||
|
[19:39:17.699] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.699] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.699] Info: Pushing 0x 4da to the stack.
|
||||||
|
[19:39:17.699] Info: Pushing 0x 3b5 to the stack.
|
||||||
|
[19:39:17.699] Info: Pushing 0x 26b to the stack.
|
||||||
|
[19:39:17.699] Info: Pushing 0x 1d6 to the stack.
|
||||||
|
[19:39:17.699] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.699] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.699] Info: Pushing 0x 4dc to the stack.
|
||||||
|
[19:39:17.699] Info: Pushing 0x 3b9 to the stack.
|
||||||
|
[19:39:17.699] Info: Pushing 0x 272 to the stack.
|
||||||
|
[19:39:17.700] Info: Pushing 0x 1e5 to the stack.
|
||||||
|
[19:39:17.700] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.700] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.700] Info: Pushing 0x 4ca to the stack.
|
||||||
|
[19:39:17.700] Info: Pushing 0x 395 to the stack.
|
||||||
|
[19:39:17.700] Info: Pushing 0x 22b to the stack.
|
||||||
|
[19:39:17.700] Info: Pushing 0x 156 to the stack.
|
||||||
|
[19:39:17.700] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.700] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.700] Info: Pushing 0x 499 to the stack.
|
||||||
|
[19:39:17.700] Info: Pushing 0x 333 to the stack.
|
||||||
|
[19:39:17.700] Info: Pushing 0x 266 to the stack.
|
||||||
|
[19:39:17.700] Info: Pushing 0x 1cd to the stack.
|
||||||
|
[19:39:17.700] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.700] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.700] Info: Pushing 0x 49a to the stack.
|
||||||
|
[19:39:17.700] Info: Pushing 0x 335 to the stack.
|
||||||
|
[19:39:17.700] Info: Pushing 0x 26a to the stack.
|
||||||
|
[19:39:17.701] Info: Pushing 0x 1d4 to the stack.
|
||||||
|
[19:39:17.701] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.702] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.702] Info: Pushing 0x 49f to the stack.
|
||||||
|
[19:39:17.702] Info: Pushing 0x 33f to the stack.
|
||||||
|
[19:39:17.702] Info: Pushing 0x 27e to the stack.
|
||||||
|
[19:39:17.702] Info: Pushing 0x 1fd to the stack.
|
||||||
|
[19:39:17.702] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.702] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.702] Info: Pushing 0x 4fb to the stack.
|
||||||
|
[19:39:17.702] Info: Pushing 0x 3f7 to the stack.
|
||||||
|
[19:39:17.702] Info: Pushing 0x 2ee to the stack.
|
||||||
|
[19:39:17.702] Info: Pushing 0x 1dc to the stack.
|
||||||
|
[19:39:17.702] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.702] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.702] Info: Pushing 0x 4bb to the stack.
|
||||||
|
[19:39:17.702] Info: Pushing 0x 377 to the stack.
|
||||||
|
[19:39:17.702] Info: Pushing 0x 2ef to the stack.
|
||||||
|
[19:39:17.703] Info: Pushing 0x 1df to the stack.
|
||||||
|
[19:39:17.703] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.703] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.703] Info: Pushing 0x 4bf to the stack.
|
||||||
|
[19:39:17.703] Info: Pushing 0x 37f to the stack.
|
||||||
|
[19:39:17.703] Info: Pushing 0x 2fe to the stack.
|
||||||
|
[19:39:17.703] Info: Pushing 0x 1fd to the stack.
|
||||||
|
[19:39:17.703] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.703] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.703] Info: Pushing 0x 4b9 to the stack.
|
||||||
|
[19:39:17.703] Info: Pushing 0x 373 to the stack.
|
||||||
|
[19:39:17.703] Info: Pushing 0x 2e7 to the stack.
|
||||||
|
[19:39:17.703] Info: Pushing 0x 1cf to the stack.
|
||||||
|
[19:39:17.703] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.703] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.703] Info: Pushing 0x 49e to the stack.
|
||||||
|
[19:39:17.703] Info: Pushing 0x 33d to the stack.
|
||||||
|
[19:39:17.703] Info: Pushing 0x 27a to the stack.
|
||||||
|
[19:39:17.705] Info: Pushing 0x 1f5 to the stack.
|
||||||
|
[19:39:17.705] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.705] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.705] Info: Pushing 0x 433 to the stack.
|
||||||
|
[19:39:17.705] Info: Pushing 0x 366 to the stack.
|
||||||
|
[19:39:17.705] Info: Pushing 0x 2cd to the stack.
|
||||||
|
[19:39:17.705] Info: Pushing 0x 19a to the stack.
|
||||||
|
[19:39:17.705] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.705] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.705] Info: Pushing 0x 435 to the stack.
|
||||||
|
[19:39:17.705] Info: Pushing 0x 36a to the stack.
|
||||||
|
[19:39:17.705] Info: Pushing 0x 2d4 to the stack.
|
||||||
|
[19:39:17.705] Info: Pushing 0x 1a9 to the stack.
|
||||||
|
[19:39:17.705] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:17.705] Info: Pushing 0x 2b to the stack.
|
||||||
|
[19:39:17.705] Info: Pushing 0x 43e to the stack.
|
||||||
|
[19:39:17.705] Info: Pushing 0x 37c to the stack.
|
||||||
|
[19:39:17.705] Info: Pushing 0x 2f9 to the stack.
|
||||||
|
[19:39:17.705] Info: Pushing 0x 1f3 to the stack.
|
||||||
|
[19:39:17.705] Info: Returning from 0x a8 to 0x 2b
|
||||||
|
[19:39:17.705] Info: Pushing 0x 2e to the stack.
|
||||||
|
[19:39:17.705] Info: Pushing 0x 4e7 to the stack.
|
||||||
|
[19:39:17.706] Info: Pushing 0x 3ce to the stack.
|
||||||
|
[19:39:17.706] Info: Pushing 0x 29c to the stack.
|
||||||
|
[19:39:17.706] Info: Pushing 0x 139 to the stack.
|
||||||
|
[19:39:17.706] Info: Returning from 0x a8 to 0x 2e
|
||||||
|
[19:39:22.038] Info: Pushing 0x 153 to the stack.
|
||||||
|
[19:39:22.042] Info: Returning from 0x2c20 to 0x 153
|
||||||
|
[19:39:22.042] Info: Pushing 0x 159 to the stack.
|
||||||
|
[19:39:22.042] Info: Returning from 0x2b94 to 0x 159
|
||||||
|
[19:39:22.042] Info: Pushing 0x 15e to the stack.
|
||||||
|
[19:39:22.056] Info: Returning from 0x2c47 to 0x 15e
|
||||||
|
[19:39:22.136] Info: Pushing 0x 19a to the stack.
|
||||||
|
[19:39:22.136] Info: Returning from 0x71de to 0x 19a
|
||||||
|
[19:39:22.136] Info: Pushing 0x 1c5 to the stack.
|
||||||
|
[19:39:22.136] Info: Pushing 0x1f8c to the stack.
|
||||||
|
[19:39:22.136] Info: Pushing 0x 80 to the stack.
|
||||||
|
[19:39:22.136] Info: Pushing 0x ff to the stack.
|
||||||
|
[19:39:22.136] Info: Pushing 0xf810 to the stack.
|
||||||
|
[19:39:22.136] Info: Pushing 0xc000 to the stack.
|
||||||
|
[19:39:22.139] Info: Returning from 0x2c38 to 0x1f8c
|
||||||
|
[19:39:22.139] Info: Returning from 0x1f8d to 0x 1c5
|
||||||
|
[19:39:22.139] Info: Pushing 0x 1c8 to the stack.
|
||||||
|
[19:39:22.139] Info: Pushing 0x 203 to the stack.
|
||||||
|
[19:39:22.139] Info: Pushing 0x 80 to the stack.
|
||||||
|
[19:39:22.139] Info: Pushing 0x 168 to the stack.
|
||||||
|
[19:39:22.139] Info: Pushing 0xf810 to the stack.
|
||||||
|
[19:39:22.140] Info: Pushing 0xc100 to the stack.
|
||||||
|
[19:39:22.144] Info: Returning from 0x2c38 to 0x 203
|
||||||
|
[19:39:22.144] Info: Pushing 0x 206 to the stack.
|
||||||
|
[19:39:22.144] Info: Pushing 0x 168 to the stack.
|
||||||
|
[19:39:22.144] Info: Pushing 0x1b92 to the stack.
|
||||||
|
[19:39:22.144] Info: Pushing 0x 168 to the stack.
|
||||||
|
[19:39:22.144] Info: Pushing 0xf810 to the stack.
|
||||||
|
[19:39:22.144] Info: Pushing 0xc100 to the stack.
|
||||||
|
[19:39:22.144] Info: Pushing 0x 0 to the stack.
|
||||||
|
[19:39:22.144] Info: Pushing 0x3eff to the stack.
|
||||||
|
[19:39:22.144] Info: Returning from 0x27bd to 0x1b92
|
||||||
|
[19:39:22.144] Info: Pushing 0xffa0 to the stack.
|
||||||
|
[19:39:22.144] Info: Pushing 0x1b96 to the stack.
|
||||||
|
[19:39:22.144] Info: Pushing 0xc100 to the stack.
|
||||||
|
[19:39:22.144] Info: Pushing 0x 168 to the stack.
|
||||||
|
[19:39:22.144] Info: Pushing 0x1bae to the stack.
|
||||||
|
[19:39:22.144] Info: Pushing 0x 168 to the stack.
|
||||||
|
[19:39:22.144] Info: Pushing 0xf810 to the stack.
|
||||||
|
[19:39:22.145] Info: Returning from 0x1f4d to 0x1bae
|
||||||
|
[19:39:22.145] Info: Returning from 0x1bc4 to 0x1b96
|
||||||
|
[19:39:22.145] Info: Pushing 0x1b99 to the stack.
|
||||||
|
[19:39:22.145] Info: Returning from 0x1f7f to 0x1b99
|
||||||
|
[19:39:22.145] Warning: Attempting to write to ROM at address: 0x 0.
|
||||||
|
[19:39:22.145] Info: Pushing 0x 167 to the stack.
|
||||||
|
[19:39:22.145] Info: Pushing 0x1b92 to the stack.
|
||||||
|
[19:39:22.145] Info: Pushing 0x 167 to the stack.
|
||||||
|
[19:39:22.145] Info: Pushing 0x 0 to the stack.
|
||||||
|
[19:39:22.145] Info: Pushing 0xc101 to the stack.
|
||||||
|
[19:39:22.145] Info: Pushing 0x f to the stack.
|
||||||
|
[19:39:22.145] Info: Pushing 0x3eff to the stack.
|
||||||
|
[19:39:22.145] Info: Returning from 0x27bd to 0x1b92
|
||||||
|
[19:39:22.145] Info: Pushing 0xffa0 to the stack.
|
||||||
|
[19:39:22.145] Info: Pushing 0x1b96 to the stack.
|
||||||
|
[19:39:22.145] Info: Pushing 0xc101 to the stack.
|
||||||
|
[19:39:22.145] Info: Pushing 0x 167 to the stack.
|
||||||
|
[19:39:22.145] Info: Pushing 0x1bae to the stack.
|
||||||
|
[19:39:22.145] Info: Pushing 0x 167 to the stack.
|
||||||
|
[19:39:22.145] Info: Pushing 0x 0 to the stack.
|
||||||
|
[19:39:22.146] Info: Returning from 0x1f4d to 0x1bae
|
||||||
|
[19:39:22.147] Info: Returning from 0x1bc4 to 0x1b96
|
||||||
|
[19:39:22.147] Info: Pushing 0x1b99 to the stack.
|
||||||
|
[19:39:22.147] Info: Returning from 0x1f7f to 0xffa0
|
||||||
|
[19:39:22.147] Info: Pushing 0xfbc3 to the stack.
|
||||||
|
[19:39:22.148] Info: Returning from 0xff8a to 0x 0
|
||||||
|
[19:39:22.148] Info: Pushing 0xfbc3 to the stack.
|
||||||
|
[19:39:22.152] Info: Returning from 0xff47 to 0x 0
|
||||||
|
[19:39:22.152] Info: Pushing 0xfbc3 to the stack.
|
||||||
|
[19:39:22.152] Error: Unimplemented opcode 0xfd at 0xfbc4!
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>sixtenhugosson</groupId>
|
||||||
|
<artifactId>playing-coffee</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>playing-coffee</name>
|
||||||
|
<description>A GameBoy emulator written in Java.</description>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.13.1</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,86 @@
|
||||||
|
Game Boy Sound Hardware Tests
|
||||||
|
-----------------------------
|
||||||
|
These tests verify aspects of the sound hardware that the CPU can
|
||||||
|
observe. The ROMs and GBSs are either for DMG or CGB hardware, as there
|
||||||
|
are several differences.
|
||||||
|
|
||||||
|
|
||||||
|
Multi-ROM
|
||||||
|
---------
|
||||||
|
In the main directory is a single ROM/GBS which runs all the tests. It
|
||||||
|
prints a test's number, runs the test, then "ok" if it passes, otherwise
|
||||||
|
a failure code. Once all tests have completed it either reports that all
|
||||||
|
tests passed, or reports the number of the first failed test as the
|
||||||
|
result code (1 = first). Finally, it makes several beeps. If a test
|
||||||
|
fails, it can be run on its own by finding the corresponding ROM/GBS in
|
||||||
|
the singles directories.
|
||||||
|
|
||||||
|
Ths compact format on screen is to avoid having the results scroll off
|
||||||
|
the top, so the test can be started and allowed to run without having to
|
||||||
|
constantly monitor the display.
|
||||||
|
|
||||||
|
|
||||||
|
Failure information
|
||||||
|
-------------------
|
||||||
|
For more information about a failure code or information printed, see
|
||||||
|
the test's source code in source/. To find failure code N, search for
|
||||||
|
"set_test N", which will usually be before the subtest which failed.
|
||||||
|
|
||||||
|
|
||||||
|
Flashes, clicks, other glitches
|
||||||
|
-------------------------------
|
||||||
|
Some tests might need to turn the screen off and on, or cause slight
|
||||||
|
audio clicks. This does not indicate failure, and should be ignored.
|
||||||
|
Only the test result reported at the end is important, unless stated
|
||||||
|
otherwise.
|
||||||
|
|
||||||
|
|
||||||
|
LCD support
|
||||||
|
-----------
|
||||||
|
Tests generally print information on screen. The tests will work fine if
|
||||||
|
run on an emulator with NO LCD support, or as an GBS which has no
|
||||||
|
inherent screen; in particular, the VBL wait routine has a timeout in
|
||||||
|
case LY doesn't reflect the current LCD line. The text printing will
|
||||||
|
also work if the LCD doesn't support scrolling.
|
||||||
|
|
||||||
|
|
||||||
|
Output to memory
|
||||||
|
----------------
|
||||||
|
Text output and the final result are also written to memory at $A000,
|
||||||
|
allowing testing a very minimal emulator that supports little more than
|
||||||
|
CPU and RAM. To reliably indicate that the data is from a test and not
|
||||||
|
random data, $A001-$A003 are written with a signature: $DE,$B0,$61. If
|
||||||
|
this is present, then the text string and final result status are valid.
|
||||||
|
|
||||||
|
$A000 holds the overall status. If the test is still running, it holds
|
||||||
|
$80, otherwise it holds the final result code.
|
||||||
|
|
||||||
|
All text output is appended to a zero-terminated string at $A004. An
|
||||||
|
emulator could regularly check this string for any additional
|
||||||
|
characters, and output them, allowing real-time text output, rather than
|
||||||
|
just printing the final output at the end.
|
||||||
|
|
||||||
|
|
||||||
|
GBS versions
|
||||||
|
------------
|
||||||
|
Many GBS-based tests require that the GBS player either not interrupt
|
||||||
|
the init routine with the play routine, or if they do, not interrupt the
|
||||||
|
play routine again if it hasn't returned yet. This is because many tests
|
||||||
|
need to run for a while without returning.
|
||||||
|
|
||||||
|
In addition to the other text output methods described above, GBS builds
|
||||||
|
report essential information bytes audibly, including the final result.
|
||||||
|
A byte is reported as a series of tones. The code is in binary, with a
|
||||||
|
low tone for 0 and a high tone for 1. The first tone is always a zero. A
|
||||||
|
final code of 0 means passed, 1 means failure, and 2 or higher indicates
|
||||||
|
a specific reason as listed in the source code by the corresponding
|
||||||
|
set_code line. Examples:
|
||||||
|
|
||||||
|
Tones Binary Decimal Meaning
|
||||||
|
- - - - - - - - - - - - - - - - - - - -
|
||||||
|
low 0 0 passed
|
||||||
|
low high 01 1 failed
|
||||||
|
low high low 010 2 error 2
|
||||||
|
|
||||||
|
--
|
||||||
|
Shay Green <gblargg@gmail.com>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,117 @@
|
||||||
|
; - APU registers always have some bits set when read back.
|
||||||
|
; - Wave memory can be read back freely.
|
||||||
|
; - When powered off, registers are cleared, except high bit of NR52.
|
||||||
|
; - While off, register writes are ignored, but not reads.
|
||||||
|
; - Wave RAM is always readable and writable, and unaffected by power.
|
||||||
|
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "apu.s"
|
||||||
|
|
||||||
|
main:
|
||||||
|
set_test 2,"NR10-NR51 and wave RAM write/read"
|
||||||
|
ld d,0
|
||||||
|
- call test_rw
|
||||||
|
inc d
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
set_test 3,"NR52 write/read"
|
||||||
|
wreg NR52,$00
|
||||||
|
lda NR52
|
||||||
|
cp $70
|
||||||
|
jp nz,test_failed
|
||||||
|
wreg NR52,$FF
|
||||||
|
lda NR52
|
||||||
|
cp $F0
|
||||||
|
jp nz,test_failed
|
||||||
|
|
||||||
|
set_test 4,"Powering APU shouldn't affect wave"
|
||||||
|
ld a,$37
|
||||||
|
call fill_wave
|
||||||
|
wreg NR52,$00
|
||||||
|
|
||||||
|
; Verify that wave RAM is unchanged
|
||||||
|
ld hl,WAVE
|
||||||
|
- ld a,(hl+)
|
||||||
|
cp $37
|
||||||
|
jp nz,test_failed
|
||||||
|
ld a,l
|
||||||
|
cp $40
|
||||||
|
jr nz,-
|
||||||
|
wreg NR52,$80 ; on
|
||||||
|
|
||||||
|
set_test 5,"Powering APU off should write 0 to all regs"
|
||||||
|
ld a,$FF
|
||||||
|
call fill_apu_regs
|
||||||
|
wreg NR52,$00
|
||||||
|
wreg NR52,$80
|
||||||
|
call regs_should_be_clear
|
||||||
|
|
||||||
|
set_test 6,"When off, should ignore writes to registers"
|
||||||
|
wreg NR52,$00
|
||||||
|
ld a,$FF
|
||||||
|
call fill_apu_regs
|
||||||
|
wreg NR52,$80
|
||||||
|
call regs_should_be_clear
|
||||||
|
wreg NR52,$80
|
||||||
|
|
||||||
|
set_test 7,"When off, should allow normal register reads"
|
||||||
|
wreg NR52,$00
|
||||||
|
call regs_should_be_clear
|
||||||
|
wreg NR52,$80
|
||||||
|
|
||||||
|
jp tests_passed
|
||||||
|
|
||||||
|
regs_should_be_clear:
|
||||||
|
ld bc,masks
|
||||||
|
ld hl,NR10
|
||||||
|
- ld a,(bc)
|
||||||
|
cp (hl)
|
||||||
|
jp nz,test_failed
|
||||||
|
inc bc
|
||||||
|
inc l
|
||||||
|
ld a,l
|
||||||
|
cp <NR52
|
||||||
|
jr nz,-
|
||||||
|
ret
|
||||||
|
|
||||||
|
test_rw:
|
||||||
|
ld bc,masks
|
||||||
|
ld hl,NR10
|
||||||
|
- ; Skip NR52
|
||||||
|
ld a,l
|
||||||
|
cp <NR52
|
||||||
|
jr z,+
|
||||||
|
|
||||||
|
; A = value that should be read back
|
||||||
|
ld a,(bc)
|
||||||
|
or d
|
||||||
|
|
||||||
|
; Write then read back and compare
|
||||||
|
ld (hl),d
|
||||||
|
cp (hl)
|
||||||
|
jp nz,test_failed
|
||||||
|
|
||||||
|
+ ; Mute channels
|
||||||
|
wreg NR51,0
|
||||||
|
|
||||||
|
; Disable wave, in case it just got enabled
|
||||||
|
; while testing register
|
||||||
|
wreg NR30,0
|
||||||
|
|
||||||
|
inc bc
|
||||||
|
inc l
|
||||||
|
ld a,l
|
||||||
|
cp <WAVE+$10
|
||||||
|
jr nz,-
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Registers are ORed with this when reading
|
||||||
|
masks:
|
||||||
|
.byte $80,$3F,$00,$FF,$BF ; NR10-NR15
|
||||||
|
.byte $FF,$3F,$00,$FF,$BF ; NR20-NR25
|
||||||
|
.byte $7F,$FF,$9F,$FF,$BF ; NR30-NR35
|
||||||
|
.byte $FF,$FF,$00,$00,$BF ; NR40-NR45
|
||||||
|
.byte $00,$00,$70 ; NR50-NR52
|
||||||
|
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||||
|
.byte $00,$00,$00,$00,$00,$00,$00,$00 ; Wave RAM
|
||||||
|
.byte $00,$00,$00,$00,$00,$00,$00,$00
|
||||||
|
|
@ -0,0 +1,163 @@
|
||||||
|
; Tests basic length counter operation
|
||||||
|
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "test_chan.s"
|
||||||
|
|
||||||
|
main:
|
||||||
|
test_all_chans
|
||||||
|
jp tests_passed
|
||||||
|
|
||||||
|
begin:
|
||||||
|
call sync_apu
|
||||||
|
delay 2048 ; avoid extra clocking due to quirks
|
||||||
|
wchn 4,$40 ; avoid extra clocking due to quirks
|
||||||
|
wchn 1,-4 ; length = 4
|
||||||
|
wchn 4,$C0 ; trigger, enabling channel
|
||||||
|
ret
|
||||||
|
|
||||||
|
should_be_on:
|
||||||
|
lda chan_mask
|
||||||
|
ld b,a
|
||||||
|
lda NR52
|
||||||
|
and b
|
||||||
|
jp z,test_failed
|
||||||
|
ret
|
||||||
|
|
||||||
|
should_be_almost_off:
|
||||||
|
call should_be_on
|
||||||
|
delay_apu 1
|
||||||
|
should_be_off:
|
||||||
|
lda chan_mask
|
||||||
|
ld b,a
|
||||||
|
lda NR52
|
||||||
|
and b
|
||||||
|
jp nz,test_failed
|
||||||
|
ret
|
||||||
|
|
||||||
|
test_chan:
|
||||||
|
set_test 2,"Length becoming 0 should clear status"
|
||||||
|
call begin
|
||||||
|
delay_apu 3
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 3,"Length can be reloaded at any time"
|
||||||
|
call begin
|
||||||
|
wchn 1,-10 ; length = 10
|
||||||
|
delay_apu 9
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 4,"Attempting to load length with 0 should load with maximum"
|
||||||
|
call begin
|
||||||
|
wchn 1,0 ; length = maximum
|
||||||
|
lda chan_maxlen
|
||||||
|
dec a
|
||||||
|
call delay_apu_cycles
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 5,"Trigger shouldn't affect length"
|
||||||
|
call begin
|
||||||
|
delay_apu 1
|
||||||
|
wchn 4,$C0 ; length unaffected
|
||||||
|
delay_apu 2
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 6,"Trigger should treat 0 length as maximum"
|
||||||
|
call begin
|
||||||
|
delay_apu 4 ; clocks length to 0
|
||||||
|
wchn 4,$C0 ; trigger converts 0 to maximum
|
||||||
|
lda chan_maxlen
|
||||||
|
dec a
|
||||||
|
call delay_apu_cycles
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 7,"Trigger with disabled length should convert ","0 length to maximum"
|
||||||
|
call begin
|
||||||
|
delay_apu 4 ; clocks length to 0
|
||||||
|
wchn 4,$00 ; disable length
|
||||||
|
wchn 4,$80 ; trigger converts 0 to maximum
|
||||||
|
wchn 4,$40 ; enable length
|
||||||
|
lda chan_maxlen
|
||||||
|
dec a
|
||||||
|
call delay_apu_cycles
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 8,"Disabling length shouldn't re-enable channel"
|
||||||
|
call begin
|
||||||
|
delay_apu 4 ; clocks length to 0
|
||||||
|
call should_be_off
|
||||||
|
wchn 4,0 ; disable length
|
||||||
|
call should_be_off
|
||||||
|
|
||||||
|
set_test 9,"Disabling length should stop length clocking"
|
||||||
|
call begin
|
||||||
|
wchn 4,0 ; disable length
|
||||||
|
delay_apu 4 ; length isn't affected
|
||||||
|
wchn 4,$40 ; enable length
|
||||||
|
delay_apu 3 ; clocks length to 1
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 10,"Reloading shouldn't re-enable channel"
|
||||||
|
call begin
|
||||||
|
delay_apu 4 ; clocks length to 0
|
||||||
|
call should_be_off
|
||||||
|
wchn 1,-2 ; length = 2
|
||||||
|
call should_be_off
|
||||||
|
|
||||||
|
set_test 11,"Disabled channel should still clock length"
|
||||||
|
call begin
|
||||||
|
delay_apu 4 ; clocks length to 0, disabling channel
|
||||||
|
wchn 1,-8 ; length = 8
|
||||||
|
delay_apu 4 ; clocks length to 4
|
||||||
|
wchn 4,$C0 ; trigger, enabling channel
|
||||||
|
delay_apu 3 ; clocks length to 1
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 12,"Disabled channel should still convert 0 load to max length"
|
||||||
|
call begin
|
||||||
|
delay_apu 4 ; clocks length to 0, disabling channel
|
||||||
|
wchn 1,0 ; length = maximum
|
||||||
|
delay_apu 32 ; clock length 32 times
|
||||||
|
wchn 4,$C0
|
||||||
|
lda chan_maxlen
|
||||||
|
sub 33
|
||||||
|
call delay_apu_cycles
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 13,"Disabling DAC should disable channel immediately"
|
||||||
|
call begin
|
||||||
|
delay_apu 2 ; clocks length to 2
|
||||||
|
call should_be_on
|
||||||
|
wchn 0,$00 ; if wave channel, this disables DAC
|
||||||
|
wchn 2,$07 ; if square/noise channel, this disables DAC
|
||||||
|
call should_be_off
|
||||||
|
|
||||||
|
set_test 14,"Disabled DAC should prevent enable at trigger"
|
||||||
|
call begin
|
||||||
|
wchn 0,$00 ; if wave channel, this disables DAC
|
||||||
|
wchn 2,$07 ; if square/noise channel, this disables DAC
|
||||||
|
wchn 4,$80 ; triggers channel but doesn't enable it
|
||||||
|
call should_be_off
|
||||||
|
|
||||||
|
set_test 15,"Enabling DAC shouldn't re-enable channel"
|
||||||
|
wchn 0,$80 ; if wave channel, this enables DAC
|
||||||
|
wchn 2,$10 ; if square/noise channel, this enables DAC
|
||||||
|
call begin
|
||||||
|
delay_apu 2
|
||||||
|
call should_be_on
|
||||||
|
wchn 0,$00 ; if wave channel, this disables DAC
|
||||||
|
wchn 2,$00 ; if square/noise channel, this disables DAC
|
||||||
|
call should_be_off
|
||||||
|
wchn 0,$80 ; if wave channel, this enables DAC
|
||||||
|
wchn 2,$10 ; if square/noise channel, this enables DAC
|
||||||
|
call should_be_off
|
||||||
|
|
||||||
|
set_test 16,"Volume reaching 0 shouldn't disable channel"
|
||||||
|
wchn 2,$11 ; envelope that reaches zero in less than
|
||||||
|
; 20 length clocks (if wave channel, this just sets
|
||||||
|
; volume to 0)
|
||||||
|
call begin
|
||||||
|
wchn 1,-20
|
||||||
|
delay_apu 19
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,200 @@
|
||||||
|
; Verifies length counter clocking during fifth register writes
|
||||||
|
|
||||||
|
;.define CGB_02 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "test_chan.s"
|
||||||
|
|
||||||
|
main:
|
||||||
|
test_all_chans
|
||||||
|
jp tests_passed
|
||||||
|
|
||||||
|
begin:
|
||||||
|
call sync_apu
|
||||||
|
wchn 1,-60
|
||||||
|
wchn 4,$80
|
||||||
|
ret
|
||||||
|
|
||||||
|
end:
|
||||||
|
delay_clocks 8192+1024 ; so we don't clock length when enabling it below
|
||||||
|
end_nodelay:
|
||||||
|
ld b,a
|
||||||
|
wchn 4,$C0
|
||||||
|
ld a,b
|
||||||
|
end_passive:
|
||||||
|
ld b,a
|
||||||
|
lda chan_mask
|
||||||
|
call get_len_a
|
||||||
|
cp b
|
||||||
|
jp nz,test_failed
|
||||||
|
ret
|
||||||
|
|
||||||
|
test_chan:
|
||||||
|
set_test 2,"Enabling in second half of length period ","shouldn't clock length"
|
||||||
|
call begin
|
||||||
|
wchn 1,-2 ; length = 2
|
||||||
|
delay_clocks 8256 ; delay until beginning of second half of length period
|
||||||
|
wchn 4,$40 ; enable
|
||||||
|
ld a,2
|
||||||
|
call end_nodelay
|
||||||
|
|
||||||
|
set_test 3,"Enabling in first half of length period should clock length"
|
||||||
|
call begin
|
||||||
|
wchn 1,-2 ; length = 2
|
||||||
|
delay_clocks 7900 ; delay until near-end of first half of length period
|
||||||
|
wchn 4,$40 ; enable
|
||||||
|
ld a,1
|
||||||
|
call end_nodelay
|
||||||
|
|
||||||
|
.ifdef CGB_02
|
||||||
|
set_test 4,"Keeping disabled should clock length; ","disabling or keeping enabled shouldn't"
|
||||||
|
call begin
|
||||||
|
wchn 1,-2 ; length = 2
|
||||||
|
wchn 4,$00 ; disabled -> disabled clocks as well
|
||||||
|
ld a,1
|
||||||
|
call end
|
||||||
|
|
||||||
|
call begin
|
||||||
|
wchn 4,$40 ; enable length
|
||||||
|
wchn 1,-2 ; length = 2
|
||||||
|
wchn 4,$40 ; enabled -> enabled doesn't clock
|
||||||
|
wchn 4,$00 ; enabled -> disabled doesn't clock
|
||||||
|
ld a,2
|
||||||
|
call end
|
||||||
|
.else
|
||||||
|
set_test 4,"Anything besides enabling shouldnt't clock"
|
||||||
|
call begin
|
||||||
|
wchn 4,$40 ; enable length
|
||||||
|
wchn 1,-2 ; length = 2
|
||||||
|
wchn 4,$40 ; enabled -> enabled doesn't clock
|
||||||
|
wchn 4,$00 ; enabled -> disabled doesn't clock
|
||||||
|
wchn 4,$00 ; disabled -> disabled doesn't clock
|
||||||
|
ld a,2
|
||||||
|
call end
|
||||||
|
.endif
|
||||||
|
|
||||||
|
set_test 5,"If clock makes length zero, should disable chan"
|
||||||
|
call begin
|
||||||
|
wchn 1,-1 ; length = 1
|
||||||
|
wchn 4,$40 ; enable, causing clock to zero
|
||||||
|
lda chan_mask
|
||||||
|
ld b,a
|
||||||
|
lda NR52 ; channel now disabled
|
||||||
|
and b
|
||||||
|
jp nz,test_failed
|
||||||
|
|
||||||
|
set_test 6,"If length already reached zero, shouldn't clock"
|
||||||
|
call begin
|
||||||
|
wchn 1,-1 ; length = 1
|
||||||
|
wchn 4,$40 ; enable, causing clock to zero
|
||||||
|
wchn 4,0
|
||||||
|
wchn 4,$40 ; no clock; length still 0
|
||||||
|
wchn 4,0
|
||||||
|
wchn 4,$40 ; no clock; length still 0
|
||||||
|
lda chan_maxlen; end triggers channel, which loads it with max length
|
||||||
|
call end
|
||||||
|
|
||||||
|
set_test 7,"Trigger should un-freeze length that reached zero"
|
||||||
|
call begin
|
||||||
|
wchn 1,-1 ; length = 1
|
||||||
|
wchn 4,$40 ; enable, causing clock to zero
|
||||||
|
wchn 4,$00 ; disable
|
||||||
|
wchn 4,$80 ; trigger unfreezes length, so it takes on maximum value
|
||||||
|
delay_clocks 8192
|
||||||
|
wchn 4,$40 ; enable
|
||||||
|
delay_apu 2 ; clock length by 2
|
||||||
|
lda chan_maxlen
|
||||||
|
sub 2
|
||||||
|
call end_nodelay
|
||||||
|
|
||||||
|
set_test 8,"Trigger that un-freezes enabled length should clock it"
|
||||||
|
call begin
|
||||||
|
wchn 1,-1 ; length = 1
|
||||||
|
wchn 4,$40 ; enable, causing clock to zero
|
||||||
|
wchn 4,$00 ; disable
|
||||||
|
wchn 4,$C0 ; trigger unfreezes length, and since enabled, clocks it
|
||||||
|
lda chan_maxlen
|
||||||
|
dec a
|
||||||
|
call end_nodelay
|
||||||
|
|
||||||
|
call begin
|
||||||
|
wchn 1,-1 ; length = 1
|
||||||
|
wchn 4,$40 ; enable, causing clock to zero
|
||||||
|
wchn 4,$C0 ; trigger unfreezes length, and since enabled, clocks it
|
||||||
|
lda chan_maxlen
|
||||||
|
dec a
|
||||||
|
call end_nodelay
|
||||||
|
|
||||||
|
set_test 9,"Triggering that clocks length of 1 ","should clock twice and shouldn't freeze"
|
||||||
|
call begin
|
||||||
|
wchn 1,-1 ; length = 1
|
||||||
|
wchn 4,$C0 ; trigger and enable
|
||||||
|
; First length counter is enabled, which clocks it to 0 and freezes it
|
||||||
|
; Trigger unfreezes length counter, which clocks it AGAIN
|
||||||
|
; The result is the same as the previous test, which enables separately
|
||||||
|
lda chan_maxlen
|
||||||
|
dec a
|
||||||
|
call end_nodelay
|
||||||
|
|
||||||
|
set_test 10,"Trigger shouldn't otherwise affect length"
|
||||||
|
call begin
|
||||||
|
wchn 1,0 ; length = max
|
||||||
|
delay_clocks 8192
|
||||||
|
wchn 4,$80 ; trigger
|
||||||
|
lda chan_maxlen
|
||||||
|
call end_nodelay
|
||||||
|
|
||||||
|
.ifndef CGB_02
|
||||||
|
call begin
|
||||||
|
wchn 1,0 ; length = max
|
||||||
|
wchn 4,$80 ; trigger
|
||||||
|
lda chan_maxlen
|
||||||
|
call end
|
||||||
|
|
||||||
|
call begin
|
||||||
|
wchn 1,-2 ; length = 2
|
||||||
|
wchn 4,$80 ; trigger
|
||||||
|
ld a,2
|
||||||
|
call end
|
||||||
|
.endif
|
||||||
|
|
||||||
|
set_test 11,"Disabled DAC shouldn't stop other trigger effects"
|
||||||
|
call begin
|
||||||
|
wchn 0,$00 ; disable wave DAC
|
||||||
|
wchn 2,$07 ; disable square/noise DAC
|
||||||
|
wchn 1,-1
|
||||||
|
wchn 4,$C0 ; clocks length, which becomes max
|
||||||
|
wchn 0,$80 ; enable wave DAC
|
||||||
|
wchn 2,$08 ; enable square/noise DAC
|
||||||
|
wchn 4,$80 ; trigger
|
||||||
|
lda chan_maxlen
|
||||||
|
dec a
|
||||||
|
call end
|
||||||
|
|
||||||
|
set_test 12,"Other trigger effects should still occur when disabled"
|
||||||
|
call sync_apu
|
||||||
|
wchn 0,0
|
||||||
|
wchn 4,0
|
||||||
|
wchn 1,-1
|
||||||
|
wchn 4,$40 ; len = 0
|
||||||
|
wchn 4,0
|
||||||
|
wchn 4,$40 ; len = 0
|
||||||
|
wchn 4,$80 ; len = max
|
||||||
|
wchn 4,$40 ; len = max-1
|
||||||
|
wchn 4,0
|
||||||
|
wchn 4,$40 ; len = max-2
|
||||||
|
wchn 0,$80 ; enable now
|
||||||
|
wchn 4,$C0
|
||||||
|
lda chan_maxlen
|
||||||
|
sub 3
|
||||||
|
call delay_apu_cycles
|
||||||
|
lda chan_mask
|
||||||
|
ld b,a
|
||||||
|
lda NR52
|
||||||
|
and b
|
||||||
|
jp z,test_failed
|
||||||
|
delay_apu 1
|
||||||
|
lda NR52
|
||||||
|
and b
|
||||||
|
jp nz,test_failed
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
; Calc = calculation of new frequency and check for > $7FF
|
||||||
|
; Update = modification of frequency with new calculated value
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "apu.s"
|
||||||
|
|
||||||
|
begin:
|
||||||
|
call sync_sweep
|
||||||
|
wreg NR14,$40
|
||||||
|
wreg NR11,-$21
|
||||||
|
wreg NR12,$08
|
||||||
|
ret
|
||||||
|
|
||||||
|
should_be_almost_off:
|
||||||
|
lda NR52
|
||||||
|
and $01
|
||||||
|
jp z,test_failed
|
||||||
|
delay_apu 1
|
||||||
|
should_be_off:
|
||||||
|
lda NR52
|
||||||
|
and $01
|
||||||
|
jp nz,test_failed
|
||||||
|
ret
|
||||||
|
|
||||||
|
main:
|
||||||
|
set_test 2,"If shift>0, calculates on trigger"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$01
|
||||||
|
wreg NR13,$FF
|
||||||
|
wreg NR14,$C7
|
||||||
|
call should_be_off
|
||||||
|
call begin
|
||||||
|
wreg NR10,$11
|
||||||
|
wreg NR13,$FF
|
||||||
|
wreg NR14,$C7
|
||||||
|
call should_be_off
|
||||||
|
|
||||||
|
set_test 3,"If shift=0, doesn't calculate on trigger"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$10
|
||||||
|
wreg NR13,$FF
|
||||||
|
wreg NR14,$C7
|
||||||
|
delay_apu 1
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 4,"If period=0, doesn't calculate"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$00
|
||||||
|
wreg NR13,$FF
|
||||||
|
wreg NR14,$C7
|
||||||
|
delay_apu $20
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 5,"After updating frequency, calculates a second time"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$11
|
||||||
|
wreg NR13,$00
|
||||||
|
wreg NR14,$C5
|
||||||
|
delay_apu 1
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 6,"If calculation>$7FF, disables channel"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$02
|
||||||
|
wreg NR13,$67
|
||||||
|
wreg NR14,$C6
|
||||||
|
call should_be_off
|
||||||
|
|
||||||
|
set_test 7,"If calculation<=$7FF, doesn't disable channel"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$01
|
||||||
|
wreg NR13,$55
|
||||||
|
wreg NR14,$C5
|
||||||
|
delay_apu $20
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 8,"If shift=0 and period>0, trigger enables"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$10
|
||||||
|
wreg NR13,$FF
|
||||||
|
wreg NR14,$C3
|
||||||
|
delay_apu 2
|
||||||
|
wreg NR10,$11
|
||||||
|
delay_apu 1
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 9,"If shift>0 and period=0, trigger enables"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$01
|
||||||
|
wreg NR13,$FF
|
||||||
|
wreg NR14,$C3
|
||||||
|
delay_apu 15
|
||||||
|
wreg NR10,$11
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 10,"If shift=0 and period=0, trigger disables"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$08
|
||||||
|
wreg NR13,$FF
|
||||||
|
wreg NR14,$C3
|
||||||
|
wreg NR10,$11
|
||||||
|
delay_apu $20
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 11,"If shift=0, doesn't update"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$10
|
||||||
|
wreg NR13,$FF
|
||||||
|
wreg NR14,$C3
|
||||||
|
delay_apu $20
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 12,"If period=0, doesn't update"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$01
|
||||||
|
wreg NR13,$00
|
||||||
|
wreg NR14,$C5
|
||||||
|
delay_apu $20
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
jp tests_passed
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
; Calc = calculation of new frequency and check for > $7FF
|
||||||
|
; Update = modification of frequency with new calculated value
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "apu.s"
|
||||||
|
|
||||||
|
begin:
|
||||||
|
call sync_sweep
|
||||||
|
wreg NR14,$40
|
||||||
|
wreg NR11,-$20
|
||||||
|
wreg NR12,$08
|
||||||
|
ret
|
||||||
|
|
||||||
|
should_be_almost_off:
|
||||||
|
lda NR52
|
||||||
|
and $01
|
||||||
|
jp z,test_failed
|
||||||
|
delay_apu 1
|
||||||
|
should_be_off:
|
||||||
|
lda NR52
|
||||||
|
and $01
|
||||||
|
jp nz,test_failed
|
||||||
|
ret
|
||||||
|
|
||||||
|
main:
|
||||||
|
set_test 2,"Timer treats period 0 as 8"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$11
|
||||||
|
wreg NR13,$00
|
||||||
|
wreg NR14,$C2
|
||||||
|
delay_apu 1
|
||||||
|
wreg NR10,$01 ; sweep enabled
|
||||||
|
delay_apu 3
|
||||||
|
wreg NR10,$11 ; non-zero period so calc will occur when timer reloads
|
||||||
|
delay_apu $11
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 3,"Makes private copy of frequency on trigger"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$12
|
||||||
|
wreg NR13,$04
|
||||||
|
wreg NR14,$80
|
||||||
|
wreg NR13,$00
|
||||||
|
delay_apu $39
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 4,"Exiting negate mode after calculation disables channel"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$09 ; since shift > 0, calculates sweep value at init
|
||||||
|
wreg NR13,$00
|
||||||
|
wreg NR14,$C0
|
||||||
|
delay_apu 2
|
||||||
|
wreg NR10,$10 ; neg->pos, so disables channel
|
||||||
|
call should_be_off
|
||||||
|
|
||||||
|
set_test 5,"Ending negate after it maybe changed freq disables chan"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$10 ; enable sweep
|
||||||
|
wreg NR13,$00
|
||||||
|
wreg NR14,$C0
|
||||||
|
delay_apu 2
|
||||||
|
wreg NR10,$18 ; negate mode
|
||||||
|
delay_apu 2
|
||||||
|
wreg NR10,$10 ; neg->pos, so disables channel
|
||||||
|
call should_be_off
|
||||||
|
|
||||||
|
set_test 6,"Ending negate mode any other way doesn't disable channel"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$1F ; use negate mode once
|
||||||
|
wreg NR14,$C0
|
||||||
|
delay_apu 2
|
||||||
|
wreg NR10,$18 ; since period > 0, doesn't calculate at init
|
||||||
|
wreg NR13,$00
|
||||||
|
wreg NR14,$C0
|
||||||
|
delay_apu 1 ; no sweep clock here
|
||||||
|
wreg NR10,$10 ; pos mode before neg mode ever used
|
||||||
|
delay_apu 1 ; sweep clock occurs here
|
||||||
|
wreg NR10,$0F ; now let neg mode be seen once, but period = 0 so no calculation is made
|
||||||
|
delay_apu 2 ; sweep clock occurs here
|
||||||
|
wreg NR10,$10 ; doesn't affect channel
|
||||||
|
delay_apu 2 ; sweep clock occurs here
|
||||||
|
wreg NR10,$1F ; let neg mode get used
|
||||||
|
delay_apu 18
|
||||||
|
wreg NR10,$79 ; period and shift can be changed without channel disabling
|
||||||
|
delay_apu 5
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 7,"Subtract mode uses two's complement"
|
||||||
|
call begin
|
||||||
|
delay 2048 ; avoids extra length clocking on CGB-02
|
||||||
|
wreg NR10,$1C
|
||||||
|
wreg NR13,$B0
|
||||||
|
wreg NR14,$85
|
||||||
|
delay_apu 2
|
||||||
|
wreg NR10,$01
|
||||||
|
wreg NR14,$C5
|
||||||
|
delay_apu $1F
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
set_test 8,"Subtract mode uses two's complement (upper bound)"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$1C
|
||||||
|
wreg NR13,$B1
|
||||||
|
wreg NR14,$85
|
||||||
|
delay_apu 2
|
||||||
|
wreg NR10,$01
|
||||||
|
wreg NR14,$C5
|
||||||
|
call should_be_off
|
||||||
|
|
||||||
|
set_test 9,"Update channel frequency only when period is reloaded"
|
||||||
|
call begin
|
||||||
|
wreg NR10,$74
|
||||||
|
wreg NR13,$06
|
||||||
|
wreg NR14,$85
|
||||||
|
delay_apu 14 ; just reloaded
|
||||||
|
wreg NR13,$06
|
||||||
|
delay_apu 13 ; if 14, fails
|
||||||
|
wreg NR10,$11
|
||||||
|
wreg NR14,$85 ; just before next reload, so freq is still $506
|
||||||
|
call should_be_almost_off
|
||||||
|
|
||||||
|
jp tests_passed
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
; Finds highest and lowest frequencies that don't overflow
|
||||||
|
; immediately on trigger, for NR10 values of $00-$07
|
||||||
|
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "apu.s"
|
||||||
|
|
||||||
|
main:
|
||||||
|
|
||||||
|
; DMG-06:
|
||||||
|
; 0555 0666 071C 0787 07C1 07E0 07F0
|
||||||
|
|
||||||
|
wreg NR12,8
|
||||||
|
ld d,$01
|
||||||
|
shift_loop:
|
||||||
|
ld a,d
|
||||||
|
sta NR10
|
||||||
|
ld bc,$87FF
|
||||||
|
- ld a,c
|
||||||
|
sta NR13
|
||||||
|
ld a,b
|
||||||
|
sta NR14
|
||||||
|
delay_clocks 40
|
||||||
|
lda NR52
|
||||||
|
and 1
|
||||||
|
jr nz,+
|
||||||
|
dec bc
|
||||||
|
bit 6,b
|
||||||
|
jr z,-
|
||||||
|
+ res 7,b
|
||||||
|
call print_bc
|
||||||
|
inc d
|
||||||
|
bit 3,d
|
||||||
|
jr z,shift_loop
|
||||||
|
call print_newline
|
||||||
|
check_crc $F604603B
|
||||||
|
|
||||||
|
; DMG-05, DMG-06, DMG-09, CGB-04, CGB-05:
|
||||||
|
; 0556 0667 071D 0788 07C2 07E1 07F1
|
||||||
|
|
||||||
|
wreg NR12,8
|
||||||
|
ld d,$01
|
||||||
|
shift_loop2:
|
||||||
|
ld a,d
|
||||||
|
sta NR10
|
||||||
|
ld bc,$8000
|
||||||
|
- ld a,c
|
||||||
|
sta NR13
|
||||||
|
ld a,b
|
||||||
|
sta NR14
|
||||||
|
delay_clocks 40
|
||||||
|
lda NR52
|
||||||
|
and 1
|
||||||
|
jr z,+
|
||||||
|
inc bc
|
||||||
|
bit 6,b
|
||||||
|
jr z,-
|
||||||
|
+ res 7,b
|
||||||
|
call print_bc
|
||||||
|
inc d
|
||||||
|
bit 3,d
|
||||||
|
jr z,shift_loop2
|
||||||
|
check_crc $5A1697EE
|
||||||
|
|
||||||
|
jp tests_passed
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
; Tests length and sweep periods, and synchronization between the two
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "apu.s"
|
||||||
|
|
||||||
|
test_timing:
|
||||||
|
; Time how long until next length clock
|
||||||
|
- inc de
|
||||||
|
ld a,(NR52)
|
||||||
|
and $01
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
;call print_de
|
||||||
|
|
||||||
|
; Error if not in 0...4 range
|
||||||
|
ld a,d
|
||||||
|
cp 0
|
||||||
|
jp nz,test_failed
|
||||||
|
ld a,e
|
||||||
|
cp 5
|
||||||
|
jp nc,test_failed
|
||||||
|
ret
|
||||||
|
|
||||||
|
main:
|
||||||
|
|
||||||
|
set_test 2,"Length period is wrong"
|
||||||
|
call sync_apu
|
||||||
|
wreg NR14,$40 ; avoids extra length clock
|
||||||
|
wreg NR11,$3F ; length = $01
|
||||||
|
wreg NR12,$08 ; silent without disabling channel
|
||||||
|
wreg NR14,$C0 ; start length
|
||||||
|
ld de,-$170
|
||||||
|
call test_timing
|
||||||
|
|
||||||
|
set_test 3,"Sweep period is wrong"
|
||||||
|
call sync_sweep
|
||||||
|
wreg NR10,$10 ; sweep period = 1
|
||||||
|
wreg NR12,$08 ; silent without disabling channel
|
||||||
|
wreg NR13,$FF ; max freq
|
||||||
|
wreg NR14,$87 ; start
|
||||||
|
ld de,-$2E4
|
||||||
|
call test_timing
|
||||||
|
|
||||||
|
set_test 4,"Sweep clock is synchronized with length"
|
||||||
|
call sync_sweep
|
||||||
|
wreg NR14,$40 ; avoids extra length clock
|
||||||
|
wreg NR11,$3F ; length = $01
|
||||||
|
wreg NR12,$08 ; silent without disabling channel
|
||||||
|
wreg NR14,$C0 ; start length
|
||||||
|
ld de,-$170
|
||||||
|
call test_timing
|
||||||
|
|
||||||
|
set_test 5,"Powering up APU MODs next frame time with 8192"
|
||||||
|
call sync_apu
|
||||||
|
ld de,-$16F
|
||||||
|
call test_power
|
||||||
|
|
||||||
|
call sync_apu
|
||||||
|
ld de,-$B5
|
||||||
|
call test_power_off
|
||||||
|
|
||||||
|
call sync_apu
|
||||||
|
delay_clocks 8192
|
||||||
|
ld de,-$B5
|
||||||
|
call test_power
|
||||||
|
|
||||||
|
call sync_apu
|
||||||
|
delay_clocks 8192
|
||||||
|
ld de,-$B5
|
||||||
|
call test_power_off
|
||||||
|
|
||||||
|
call sync_apu
|
||||||
|
ld de,-$B5
|
||||||
|
wreg NR52,$00 ; power off
|
||||||
|
delay_clocks 8192
|
||||||
|
call test_power
|
||||||
|
|
||||||
|
set_test 6,"Powering up APU resets 128 Hz sweep divider"
|
||||||
|
call sync_sweep
|
||||||
|
ld de,-$229
|
||||||
|
call test_power2
|
||||||
|
|
||||||
|
call sync_sweep
|
||||||
|
delay_apu 1
|
||||||
|
ld de,-$229
|
||||||
|
call test_power2
|
||||||
|
|
||||||
|
jp tests_passed
|
||||||
|
|
||||||
|
test_power_off:
|
||||||
|
wreg NR52,$00 ; power off
|
||||||
|
test_power:
|
||||||
|
wreg NR52,$80 ; power on
|
||||||
|
wreg NR14,$40
|
||||||
|
wreg NR11,-1 ; length = 1
|
||||||
|
wreg NR12,8
|
||||||
|
wreg NR14,$C0
|
||||||
|
jp test_timing
|
||||||
|
|
||||||
|
test_power2:
|
||||||
|
wreg NR52,$00 ; power off
|
||||||
|
wreg NR52,$80 ; power on
|
||||||
|
wreg NR10,$11
|
||||||
|
wreg NR12,8
|
||||||
|
wreg NR13,$00
|
||||||
|
wreg NR14,$84
|
||||||
|
jp test_timing
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
; On CGB, length counters are reset when powered up.
|
||||||
|
; On DMG, they are unaffected, and not clocked.
|
||||||
|
|
||||||
|
;.define REQUIRE_DMG 1
|
||||||
|
;.define REQUIRE_CGB 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "apu.s"
|
||||||
|
|
||||||
|
enable_len_ctrs:
|
||||||
|
wreg NR22,8
|
||||||
|
wreg NR24,$C0
|
||||||
|
wreg NR12,8
|
||||||
|
wreg NR14,$C0
|
||||||
|
wreg NR30,$80
|
||||||
|
wreg NR34,$C0
|
||||||
|
wreg NR42,8
|
||||||
|
wreg NR44,$C0
|
||||||
|
ret
|
||||||
|
|
||||||
|
main:
|
||||||
|
call sync_apu
|
||||||
|
|
||||||
|
ld a,0
|
||||||
|
call fill_apu_regs
|
||||||
|
|
||||||
|
; Load length counters
|
||||||
|
wreg NR41,-$33
|
||||||
|
wreg NR31,-$44
|
||||||
|
wreg NR11,-$11
|
||||||
|
wreg NR21,-$22
|
||||||
|
|
||||||
|
delay_clocks 8192
|
||||||
|
call enable_len_ctrs
|
||||||
|
|
||||||
|
; Power down. Comment out to see what would
|
||||||
|
; happen if length counters did run.
|
||||||
|
wreg NR52,$00
|
||||||
|
|
||||||
|
; Try to enable length counters
|
||||||
|
call enable_len_ctrs
|
||||||
|
|
||||||
|
; Give plenty of time for them to be clocked
|
||||||
|
delay_msec 250
|
||||||
|
|
||||||
|
; Power back on and wait a bit longer
|
||||||
|
wreg NR52,$80
|
||||||
|
;call enable_len_ctrs ; can't do this here
|
||||||
|
delay_clocks 2048
|
||||||
|
|
||||||
|
; Get values from length counters
|
||||||
|
wreg NR22,8
|
||||||
|
wreg NR24,$C0
|
||||||
|
ld a,$02
|
||||||
|
call get_len_a
|
||||||
|
push af
|
||||||
|
|
||||||
|
wreg NR12,8
|
||||||
|
wreg NR14,$C0
|
||||||
|
ld a,$01
|
||||||
|
call get_len_a
|
||||||
|
push af
|
||||||
|
|
||||||
|
wreg NR30,$80
|
||||||
|
wreg NR34,$C0
|
||||||
|
ld a,$04
|
||||||
|
call get_len_a
|
||||||
|
push af
|
||||||
|
|
||||||
|
wreg NR42,8
|
||||||
|
wreg NR44,$C0
|
||||||
|
ld a,$08
|
||||||
|
call get_len_a
|
||||||
|
|
||||||
|
; Print them
|
||||||
|
call print_a
|
||||||
|
pop af
|
||||||
|
call print_a
|
||||||
|
pop af
|
||||||
|
call print_a
|
||||||
|
pop af
|
||||||
|
call print_a
|
||||||
|
|
||||||
|
check_crc_dmg_cgb $32F0CFBB,$3CF589B4
|
||||||
|
jp tests_passed
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
; Reads from wave RAM while playing, each time 2
|
||||||
|
; clocks later.
|
||||||
|
|
||||||
|
;.define REQUIRE_DMG 1
|
||||||
|
;.define REQUIRE_CGB 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "apu.s"
|
||||||
|
|
||||||
|
main:
|
||||||
|
wreg NR51,0 ; mute sound
|
||||||
|
loop_n_times test,69
|
||||||
|
check_crc_dmg_cgb $118A3620,$270DA9A3
|
||||||
|
jp tests_passed
|
||||||
|
|
||||||
|
test:
|
||||||
|
add $99
|
||||||
|
ld b,a
|
||||||
|
|
||||||
|
; Reload wave and have its first
|
||||||
|
; sample read occur 2 clocks earlier
|
||||||
|
; each loop iteration
|
||||||
|
ld hl,wave
|
||||||
|
call load_wave
|
||||||
|
wreg NR30,$80 ; enable
|
||||||
|
wreg NR32,$00 ; silent
|
||||||
|
ld a,b
|
||||||
|
sta NR33 ; period
|
||||||
|
wreg NR34,$87 ; start
|
||||||
|
|
||||||
|
; Read from wave
|
||||||
|
wreg NR33,-2 ; period = 4
|
||||||
|
delay_clocks 176
|
||||||
|
lda WAVE
|
||||||
|
|
||||||
|
call print_a
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
wave:
|
||||||
|
.byte $00,$11,$22,$33,$44,$55,$66,$77
|
||||||
|
.byte $88,$99,$AA,$BB,$CC,$DD,$EE,$FF
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
; Retriggers wave without stopping first
|
||||||
|
|
||||||
|
;.define REQUIRE_DMG 1
|
||||||
|
;.define REQUIRE_CGB 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "apu.s"
|
||||||
|
|
||||||
|
main:
|
||||||
|
wreg NR51,0 ; mute sound
|
||||||
|
loop_n_times test,69
|
||||||
|
check_crc_dmg_cgb $533D6D4D,$8130733A
|
||||||
|
jp tests_passed
|
||||||
|
|
||||||
|
test:
|
||||||
|
add $99
|
||||||
|
ld b,a
|
||||||
|
|
||||||
|
; Reload wave and have its first
|
||||||
|
; sample read occur 2 clocks earlier
|
||||||
|
; each loop iteration
|
||||||
|
ld hl,wave
|
||||||
|
call load_wave
|
||||||
|
wreg NR30,$80 ; enable
|
||||||
|
wreg NR32,$00 ; silent
|
||||||
|
ld a,b
|
||||||
|
sta NR33 ; period
|
||||||
|
wreg NR34,$87 ; start
|
||||||
|
|
||||||
|
; Retrigger wave
|
||||||
|
wreg NR33,-2 ; period = 4
|
||||||
|
delay_clocks 168
|
||||||
|
wreg NR34,$87 ; restart
|
||||||
|
delay_clocks 40
|
||||||
|
|
||||||
|
; Print wave RAM
|
||||||
|
wreg NR30,0
|
||||||
|
ld c,$30
|
||||||
|
- ld a,($FF00+c)
|
||||||
|
call print_a
|
||||||
|
inc c
|
||||||
|
bit 6,c
|
||||||
|
jr z,-
|
||||||
|
call print_newline
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
wave:
|
||||||
|
.byte $00,$11,$22,$33,$44,$55,$66,$77
|
||||||
|
.byte $88,$99,$AA,$BB,$CC,$DD,$EE,$FF
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
; After powering sound off then on, NR12, NR14, and NR44
|
||||||
|
; are clear.
|
||||||
|
.define REQUIRE_CGB 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "apu.s"
|
||||||
|
|
||||||
|
main:
|
||||||
|
call sync_apu
|
||||||
|
|
||||||
|
ld a,$FF
|
||||||
|
call fill_apu_regs
|
||||||
|
|
||||||
|
; Power down for a moment
|
||||||
|
wreg NR52,$00
|
||||||
|
wreg NR41,-$12
|
||||||
|
wreg NR12,$F0
|
||||||
|
delay_msec 100
|
||||||
|
wreg NR52,$80
|
||||||
|
|
||||||
|
set_test 2,"Powering off should clear NR12"
|
||||||
|
call sync_apu
|
||||||
|
wreg NR14,$80
|
||||||
|
lda NR52
|
||||||
|
and $01
|
||||||
|
jp nz,test_failed
|
||||||
|
|
||||||
|
set_test 3,"Powering off should clear NR13"
|
||||||
|
call sync_apu
|
||||||
|
wreg NR10,$11
|
||||||
|
wreg NR12,$08
|
||||||
|
wreg NR14,$80
|
||||||
|
delay_apu 20
|
||||||
|
lda NR52
|
||||||
|
and $01
|
||||||
|
jp z,test_failed
|
||||||
|
|
||||||
|
set_test 4,"Powering off should clear NR41"
|
||||||
|
call sync_apu
|
||||||
|
delay_clocks 8192 ; avoids extra length clocking
|
||||||
|
wreg NR42,$08
|
||||||
|
wreg NR44,$C0
|
||||||
|
delay_apu 63
|
||||||
|
lda NR52
|
||||||
|
and $08
|
||||||
|
jp z,test_failed
|
||||||
|
delay_apu 1
|
||||||
|
lda NR52
|
||||||
|
and $08
|
||||||
|
jp nz,test_failed
|
||||||
|
|
||||||
|
jp tests_passed
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
; Tests wave channel timer reload and phase rest on trigger,
|
||||||
|
; and access to wave RAM while playing.
|
||||||
|
.define REQUIRE_CGB 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "apu.s"
|
||||||
|
|
||||||
|
main:
|
||||||
|
ld hl,wave
|
||||||
|
call load_wave
|
||||||
|
wreg NR32,0
|
||||||
|
|
||||||
|
set_test 2,"Timer period or phase resetting is wrong"
|
||||||
|
wreg NR30,$80
|
||||||
|
wreg NR33,$00
|
||||||
|
wreg NR34,$80
|
||||||
|
delay_clocks 1024
|
||||||
|
wreg NR34,$80
|
||||||
|
ld c,$31
|
||||||
|
ld de,-$FE
|
||||||
|
call test_wave
|
||||||
|
|
||||||
|
set_test 3,"Current byte readable at any wave addr"
|
||||||
|
wreg NR30,$80
|
||||||
|
wreg NR33,$00
|
||||||
|
wreg NR34,$80
|
||||||
|
ld c,$3C
|
||||||
|
ld de,-$FE
|
||||||
|
call test_wave
|
||||||
|
|
||||||
|
set_test 5,"Normal access when chan disabled"
|
||||||
|
wreg NR30,$80
|
||||||
|
wreg NR33,$00
|
||||||
|
wreg NR34,$80
|
||||||
|
wreg NR30,$00 ; disable chan
|
||||||
|
wreg NR30,$80 ; DAC on
|
||||||
|
ld c,$31
|
||||||
|
ld de,0
|
||||||
|
call test_wave
|
||||||
|
|
||||||
|
set_test 6,"Write test"
|
||||||
|
wreg NR30,$80
|
||||||
|
wreg NR33,$F0
|
||||||
|
wreg NR34,$87
|
||||||
|
delay_clocks 256
|
||||||
|
wreg $FF30,$BC
|
||||||
|
wreg NR30,0
|
||||||
|
ld a,($FF34)
|
||||||
|
cp $BC
|
||||||
|
jp nz,test_failed
|
||||||
|
|
||||||
|
set_test 7,"Timer period change"
|
||||||
|
wreg NR30,$80
|
||||||
|
wreg NR33,$00
|
||||||
|
wreg NR34,$87
|
||||||
|
wreg NR33,$F0
|
||||||
|
ld c,$30
|
||||||
|
ld de,-$E
|
||||||
|
call test_wave
|
||||||
|
|
||||||
|
set_test 8,"Frequency 0 is valid"
|
||||||
|
wreg NR30,$80
|
||||||
|
wreg NR33,$00
|
||||||
|
wreg NR34,$80
|
||||||
|
ld c,$30
|
||||||
|
ld de,-$FE
|
||||||
|
call test_wave
|
||||||
|
|
||||||
|
set_test 9,"Maintains phase properly when vol = 0"
|
||||||
|
wreg NR30,$80
|
||||||
|
wreg NR32,0
|
||||||
|
wreg NR33,$00
|
||||||
|
wreg NR34,$87
|
||||||
|
ld c,$30
|
||||||
|
ld de,-$1E
|
||||||
|
call test_wave
|
||||||
|
|
||||||
|
set_test 10,"Maintains phase properly when stereo = 0"
|
||||||
|
wreg NR51,$00
|
||||||
|
wreg NR30,$80
|
||||||
|
wreg NR33,$00
|
||||||
|
wreg NR34,$87
|
||||||
|
ld c,$30
|
||||||
|
ld de,-$1E
|
||||||
|
call test_wave
|
||||||
|
|
||||||
|
jp tests_passed
|
||||||
|
|
||||||
|
test_wave:
|
||||||
|
- inc de ; 8
|
||||||
|
ld a,($FF00+c) ; 8
|
||||||
|
or a ; 4
|
||||||
|
jr z,- ; 12
|
||||||
|
|
||||||
|
;call print_a
|
||||||
|
;call print_de
|
||||||
|
|
||||||
|
cp $11
|
||||||
|
jp nz,test_failed
|
||||||
|
|
||||||
|
|
||||||
|
; Error if not in 0...4 range
|
||||||
|
ld a,d
|
||||||
|
cp 0
|
||||||
|
jp nz,test_failed
|
||||||
|
ld a,e
|
||||||
|
cp 5
|
||||||
|
jp nc,test_failed
|
||||||
|
ret
|
||||||
|
|
||||||
|
wave:
|
||||||
|
.byte $00,$11,$22,$33,$44,$55,$66,$77
|
||||||
|
.byte $88,$99,$AA,$BB,$CC,$DD,$EE,$FF
|
||||||
|
|
@ -0,0 +1,139 @@
|
||||||
|
; Build as GBS music file
|
||||||
|
|
||||||
|
.memoryMap
|
||||||
|
defaultSlot 0
|
||||||
|
slot 0 $2000 size $2000
|
||||||
|
slot 1 $C000 size $2000
|
||||||
|
.endMe
|
||||||
|
|
||||||
|
.romBankSize $2000
|
||||||
|
.romBanks 2
|
||||||
|
|
||||||
|
.define RST_OFFSET $70
|
||||||
|
|
||||||
|
.ifndef GBS_TMA
|
||||||
|
.define GBS_TMA 0
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.ifndef GBS_TAC
|
||||||
|
.define GBS_TAC 0
|
||||||
|
.endif
|
||||||
|
|
||||||
|
;;;; GBS music file header
|
||||||
|
|
||||||
|
.ifndef CUSTOM_HEADER
|
||||||
|
.byte "GBS"
|
||||||
|
.byte 1,1,1 ; vers, song count, first song
|
||||||
|
.word load_addr, reset, gbs_play_, std_stack
|
||||||
|
.byte GBS_TMA,GBS_TAC ; timer
|
||||||
|
.endif
|
||||||
|
.org $10
|
||||||
|
.ds $60,0
|
||||||
|
load_addr:
|
||||||
|
.org RST_OFFSET+$70 ; space for RST vectors
|
||||||
|
.ds $148-RST_OFFSET-$70,0
|
||||||
|
.org $150 ; wla insists on generating GB header
|
||||||
|
|
||||||
|
gbs_play_:
|
||||||
|
jp gbs_play ; GBS spec disallows having gbs_play in RAM
|
||||||
|
|
||||||
|
;;;; Shell
|
||||||
|
|
||||||
|
.include "shell.s"
|
||||||
|
|
||||||
|
.define gbs_idle nv_ram
|
||||||
|
.redefine nv_ram nv_ram+2
|
||||||
|
|
||||||
|
init_runtime:
|
||||||
|
; Identify as DMG hardware
|
||||||
|
ld a,$01
|
||||||
|
ld (gb_id),a
|
||||||
|
|
||||||
|
; Save return address
|
||||||
|
pop hl
|
||||||
|
ld a,l
|
||||||
|
ld (gbs_idle),a
|
||||||
|
ld a,h
|
||||||
|
ld (gbs_idle+1),a
|
||||||
|
|
||||||
|
; Delay 1/4 second to give time
|
||||||
|
; for GBS player to interrupt with
|
||||||
|
; play, if it's going to do so
|
||||||
|
delay_msec 250
|
||||||
|
|
||||||
|
.ifndef CUSTOM_PLAY
|
||||||
|
gbs_play:
|
||||||
|
.endif
|
||||||
|
; Get return address
|
||||||
|
ld a,(gbs_idle)
|
||||||
|
ld l,a
|
||||||
|
ld a,(gbs_idle+1)
|
||||||
|
ld h,a
|
||||||
|
|
||||||
|
; If zero, then play interrupted init
|
||||||
|
; call, or another play call, and we
|
||||||
|
; can't run the program properly.
|
||||||
|
or l
|
||||||
|
jp z,internal_error
|
||||||
|
|
||||||
|
setw gbs_idle,0
|
||||||
|
jp hl
|
||||||
|
|
||||||
|
|
||||||
|
; Reports A in binary as high and low tones, with
|
||||||
|
; leading low tone for reference. Omits leading
|
||||||
|
; zeroes.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
play_byte:
|
||||||
|
push af
|
||||||
|
push hl
|
||||||
|
|
||||||
|
; HL = (A << 1) | 1
|
||||||
|
scf
|
||||||
|
rla
|
||||||
|
ld l,a
|
||||||
|
ld h,0
|
||||||
|
rl h
|
||||||
|
|
||||||
|
; Shift left until next-to-top bit is 1
|
||||||
|
- add hl,hl
|
||||||
|
bit 6,h
|
||||||
|
jr z,-
|
||||||
|
|
||||||
|
; Reset sound
|
||||||
|
delay_msec 400
|
||||||
|
wreg NR52,0 ; sound off
|
||||||
|
wreg NR52,$80 ; sound on
|
||||||
|
wreg NR51,$FF ; mono
|
||||||
|
wreg NR50,$77 ; volume
|
||||||
|
|
||||||
|
- add hl,hl
|
||||||
|
|
||||||
|
; Low or high pitch based on bit shifted out
|
||||||
|
; of HL
|
||||||
|
ld a,0
|
||||||
|
jr nc,+
|
||||||
|
ld a,$FF
|
||||||
|
+ sta NR23
|
||||||
|
|
||||||
|
; Play short tone
|
||||||
|
wreg NR21,$A0
|
||||||
|
wreg NR22,$F0
|
||||||
|
wreg NR24,$86
|
||||||
|
delay_msec 75
|
||||||
|
wreg NR22,0
|
||||||
|
wreg NR23,$F8
|
||||||
|
wreg NR24,$87
|
||||||
|
delay_msec 200
|
||||||
|
|
||||||
|
; Loop until HL = $8000
|
||||||
|
ld a,h
|
||||||
|
xor $80
|
||||||
|
or l
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
.ends
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
; Build as GB ROM
|
||||||
|
|
||||||
|
.memoryMap
|
||||||
|
defaultSlot 0
|
||||||
|
slot 0 $0000 size $4000
|
||||||
|
slot 1 $C000 size $4000
|
||||||
|
.endMe
|
||||||
|
|
||||||
|
.romBankSize $4000
|
||||||
|
.romBanks 2
|
||||||
|
|
||||||
|
.cartridgeType 2 ; MBC1+RAM
|
||||||
|
.ramsize 02 ; 8K
|
||||||
|
.computeChecksum
|
||||||
|
.computeComplementCheck
|
||||||
|
|
||||||
|
;;;; GB ROM header
|
||||||
|
|
||||||
|
; Reserve space for RST handlers
|
||||||
|
.org $70
|
||||||
|
|
||||||
|
; Keep unused space filled, otherwise
|
||||||
|
; wla moves code here
|
||||||
|
.ds $90,0
|
||||||
|
|
||||||
|
; GB header read by bootrom
|
||||||
|
.org $100
|
||||||
|
nop
|
||||||
|
jp reset
|
||||||
|
|
||||||
|
; Nintendo logo required for proper boot
|
||||||
|
.byte $CE,$ED,$66,$66,$CC,$0D,$00,$0B
|
||||||
|
.byte $03,$73,$00,$83,$00,$0C,$00,$0D
|
||||||
|
.byte $00,$08,$11,$1F,$88,$89,$00,$0E
|
||||||
|
.byte $DC,$CC,$6E,$E6,$DD,$DD,$D9,$99
|
||||||
|
.byte $BB,$BB,$67,$63,$6E,$0E,$EC,$CC
|
||||||
|
.byte $DD,$DC,$99,$9F,$BB,$B9,$33,$3E
|
||||||
|
|
||||||
|
; Internal name
|
||||||
|
.ifdef ROM_NAME
|
||||||
|
.byte ROM_NAME
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; CGB/DMG requirements
|
||||||
|
.org $143
|
||||||
|
.ifdef REQUIRE_CGB
|
||||||
|
.byte $C0
|
||||||
|
.else
|
||||||
|
.ifndef REQUIRE_DMG
|
||||||
|
.byte $80
|
||||||
|
.endif
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; Keep unused space filled, otherwise
|
||||||
|
; wla moves code here
|
||||||
|
.org $150
|
||||||
|
.ds $2150-$150,0
|
||||||
|
|
||||||
|
;;;; Shell
|
||||||
|
|
||||||
|
.define NEED_CONSOLE 1
|
||||||
|
.include "shell.s"
|
||||||
|
|
||||||
|
init_runtime:
|
||||||
|
ret
|
||||||
|
|
||||||
|
play_byte:
|
||||||
|
ret
|
||||||
|
|
||||||
|
.ends
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,285 @@
|
||||||
|
; Scrolling text console
|
||||||
|
|
||||||
|
; Console is 20x18 characters. Buffers lines, so
|
||||||
|
; output doesn't appear until a newline or flush.
|
||||||
|
; If scrolling isn't supported (i.e. SCY is treated
|
||||||
|
; as if always zero), the first 18 lines will
|
||||||
|
; still print properly). Also works properly if
|
||||||
|
; LY isn't supported (always reads back as the same
|
||||||
|
; value).
|
||||||
|
|
||||||
|
.define console_width 20
|
||||||
|
|
||||||
|
.define console_buf bss+0
|
||||||
|
.define console_pos bss+console_width
|
||||||
|
.define console_mode bss+console_width+1
|
||||||
|
.define console_scroll bss+console_width+2
|
||||||
|
.redefine bss bss+console_width+3
|
||||||
|
|
||||||
|
|
||||||
|
; Waits for start of LCD blanking period
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
console_wait_vbl:
|
||||||
|
push bc
|
||||||
|
|
||||||
|
; Wait for start of vblank, with
|
||||||
|
; timeout in case LY doesn't work
|
||||||
|
; or LCD is disabled.
|
||||||
|
ld bc,-1250
|
||||||
|
- inc bc
|
||||||
|
ld a,b
|
||||||
|
or c
|
||||||
|
jr z,@timeout
|
||||||
|
lda LY
|
||||||
|
cp 144
|
||||||
|
jr nz,-
|
||||||
|
@timeout:
|
||||||
|
|
||||||
|
pop bc
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Initializes text console
|
||||||
|
console_init:
|
||||||
|
call console_hide
|
||||||
|
|
||||||
|
; CGB-specific inits
|
||||||
|
ld a,(gb_id)
|
||||||
|
and gb_id_cgb
|
||||||
|
call nz,@init_cgb
|
||||||
|
|
||||||
|
; Clear nametable
|
||||||
|
ld a,' '
|
||||||
|
call @fill_nametable
|
||||||
|
|
||||||
|
; Load tiles
|
||||||
|
ld hl,TILES+$200
|
||||||
|
ld c,0
|
||||||
|
call @load_tiles
|
||||||
|
ld hl,TILES+$A00
|
||||||
|
ld c,$FF
|
||||||
|
call @load_tiles
|
||||||
|
|
||||||
|
; Init state
|
||||||
|
setb console_pos,console_width
|
||||||
|
setb console_mode,0
|
||||||
|
setb console_scroll,-8
|
||||||
|
call console_scroll_up_
|
||||||
|
jr console_show
|
||||||
|
|
||||||
|
@fill_nametable:
|
||||||
|
ld hl,BGMAP0
|
||||||
|
ld b,4
|
||||||
|
- ld (hl),a
|
||||||
|
inc l
|
||||||
|
jr nz,-
|
||||||
|
inc h
|
||||||
|
dec b
|
||||||
|
jr nz,-
|
||||||
|
ret
|
||||||
|
|
||||||
|
@init_cgb:
|
||||||
|
; Clear palette
|
||||||
|
wreg $FF68,$80
|
||||||
|
ld b,16
|
||||||
|
- wreg $FF69,$FF
|
||||||
|
wreg $FF69,$7F
|
||||||
|
wreg $FF69,$00
|
||||||
|
wreg $FF69,$00
|
||||||
|
wreg $FF69,$00
|
||||||
|
wreg $FF69,$00
|
||||||
|
wreg $FF69,$00
|
||||||
|
wreg $FF69,$00
|
||||||
|
dec b
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
; Clear attributes
|
||||||
|
wreg VBK,1
|
||||||
|
ld a,0
|
||||||
|
call @fill_nametable
|
||||||
|
|
||||||
|
wreg VBK,0
|
||||||
|
ret
|
||||||
|
|
||||||
|
@load_tiles:
|
||||||
|
ld de,ASCII
|
||||||
|
ld b,96
|
||||||
|
-- push bc
|
||||||
|
ld b,8
|
||||||
|
- ld a,(de)
|
||||||
|
inc de
|
||||||
|
xor c
|
||||||
|
ldi (hl),a
|
||||||
|
ldi (hl),a
|
||||||
|
dec b
|
||||||
|
jr nz,-
|
||||||
|
pop bc
|
||||||
|
dec b
|
||||||
|
jr nz,--
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Shows console display
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
console_show:
|
||||||
|
push af
|
||||||
|
|
||||||
|
; Enable LCD
|
||||||
|
call console_wait_vbl
|
||||||
|
wreg LCDC,$91
|
||||||
|
wreg SCX,0
|
||||||
|
wreg BGP,$E4
|
||||||
|
|
||||||
|
jp console_apply_scroll_
|
||||||
|
|
||||||
|
|
||||||
|
; Hides console display by turning LCD off
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
console_hide:
|
||||||
|
push af
|
||||||
|
|
||||||
|
; LCD off
|
||||||
|
call console_wait_vbl
|
||||||
|
wreg LCDC,$11
|
||||||
|
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Changes to normal text mode
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
console_normal:
|
||||||
|
xor a
|
||||||
|
jr console_set_mode
|
||||||
|
|
||||||
|
; Changes to inverse text mode
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
console_inverse:
|
||||||
|
ld a,$80
|
||||||
|
|
||||||
|
; Changes console mode to A.
|
||||||
|
; 0: Normal, $80: Inverse
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
console_set_mode:
|
||||||
|
and $80
|
||||||
|
ld (console_mode),a
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Prints char A to console. Will not appear until
|
||||||
|
; a newline or flush occurs.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
console_print:
|
||||||
|
push af
|
||||||
|
|
||||||
|
cp 10
|
||||||
|
jr z,console_newline_
|
||||||
|
|
||||||
|
push hl
|
||||||
|
push af
|
||||||
|
ld hl,console_pos
|
||||||
|
ldi a,(hl)
|
||||||
|
cp <console_buf
|
||||||
|
jr nz,@not_at_end
|
||||||
|
|
||||||
|
; Newline if at end of current line. If this
|
||||||
|
; were done after writing to buffer, calling
|
||||||
|
; console_newline would print extra newline.
|
||||||
|
; Doing it before eliminates this.
|
||||||
|
|
||||||
|
; Ignore any spaces at end of line
|
||||||
|
pop af
|
||||||
|
cp ' '
|
||||||
|
jr z,@ignore_space
|
||||||
|
call console_newline
|
||||||
|
push af
|
||||||
|
|
||||||
|
@not_at_end:
|
||||||
|
pop af
|
||||||
|
or (hl) ; apply current attributes
|
||||||
|
dec l ; hl = console_pos
|
||||||
|
dec (hl) ; console_pos = console_pos - 1
|
||||||
|
ld l,(hl) ; hl = position in buffer
|
||||||
|
ld (hl),a
|
||||||
|
|
||||||
|
@ignore_space
|
||||||
|
pop hl
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Displays current line and starts new one
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
console_newline:
|
||||||
|
push af
|
||||||
|
console_newline_:
|
||||||
|
call console_wait_vbl
|
||||||
|
call console_flush_
|
||||||
|
call console_scroll_up_
|
||||||
|
call console_flush_
|
||||||
|
jp console_apply_scroll_
|
||||||
|
|
||||||
|
|
||||||
|
console_scroll_up_:
|
||||||
|
push bc
|
||||||
|
push hl
|
||||||
|
|
||||||
|
; Scroll up 8 pixels
|
||||||
|
ld a,(console_scroll)
|
||||||
|
add 8
|
||||||
|
ld (console_scroll),a
|
||||||
|
|
||||||
|
; Start new clear line
|
||||||
|
ld a,' '
|
||||||
|
ld hl,console_buf + console_width - 1
|
||||||
|
ld b,console_width
|
||||||
|
- ldd (hl),a
|
||||||
|
dec b
|
||||||
|
jr nz,-
|
||||||
|
setb console_pos,<(console_buf + console_width)
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop bc
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Displays current line's contents without scrolling.
|
||||||
|
; Preserved: A, BC, DE, HL
|
||||||
|
console_flush:
|
||||||
|
push af
|
||||||
|
call console_wait_vbl
|
||||||
|
call console_flush_
|
||||||
|
console_apply_scroll_:
|
||||||
|
ld a,(console_scroll)
|
||||||
|
sub 136
|
||||||
|
sta SCY
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
console_flush_:
|
||||||
|
push de
|
||||||
|
push hl
|
||||||
|
|
||||||
|
; Address of row in nametable
|
||||||
|
ld a,(console_scroll)
|
||||||
|
ld l,a
|
||||||
|
ld h,(>BGMAP0) >> 2
|
||||||
|
add hl,hl
|
||||||
|
add hl,hl
|
||||||
|
|
||||||
|
; Copy line
|
||||||
|
ld de,console_buf + console_width
|
||||||
|
- dec e
|
||||||
|
ld a,(de)
|
||||||
|
ldi (hl),a
|
||||||
|
ld a,e
|
||||||
|
cp <console_buf
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop de
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
ASCII:
|
||||||
|
.incbin "console.bin"
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
; CRC-32 checksum calculation
|
||||||
|
|
||||||
|
.define checksum dp+0 ; little-endian, complemented
|
||||||
|
.redefine dp dp+4
|
||||||
|
|
||||||
|
|
||||||
|
; Initializes checksum module. Might initialize tables
|
||||||
|
; in the future.
|
||||||
|
init_crc:
|
||||||
|
jr reset_crc
|
||||||
|
|
||||||
|
|
||||||
|
; Clears CRC
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
reset_crc:
|
||||||
|
ld a,$FF
|
||||||
|
sta checksum+0
|
||||||
|
sta checksum+1
|
||||||
|
sta checksum+2
|
||||||
|
sta checksum+3
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Updates current checksum with byte A
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
; Time: 237 cycles average
|
||||||
|
update_crc:
|
||||||
|
; 65 cycles + 8*cycles per bit
|
||||||
|
; min cycles per bit: 14
|
||||||
|
; max cycles per bit: 29
|
||||||
|
push af
|
||||||
|
push bc
|
||||||
|
push de
|
||||||
|
push hl
|
||||||
|
|
||||||
|
ld hl,checksum+3
|
||||||
|
ld b,(hl)
|
||||||
|
dec l
|
||||||
|
ld c,(hl)
|
||||||
|
dec l
|
||||||
|
ld d,(hl)
|
||||||
|
dec l
|
||||||
|
xor (hl)
|
||||||
|
|
||||||
|
ld h,8
|
||||||
|
- srl b
|
||||||
|
rr c
|
||||||
|
rr d
|
||||||
|
rra
|
||||||
|
jr nc,+
|
||||||
|
ld e,a
|
||||||
|
ld a,b
|
||||||
|
xor $ED
|
||||||
|
ld b,a
|
||||||
|
ld a,c
|
||||||
|
xor $B8
|
||||||
|
ld c,a
|
||||||
|
ld a,d
|
||||||
|
xor $83
|
||||||
|
ld d,a
|
||||||
|
ld a,e
|
||||||
|
xor $20
|
||||||
|
+ dec h
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
ld h,>checksum
|
||||||
|
ldi (hl),a
|
||||||
|
ld (hl),d
|
||||||
|
inc l
|
||||||
|
ld (hl),c
|
||||||
|
inc l
|
||||||
|
ld (hl),b
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop de
|
||||||
|
pop bc
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,220 @@
|
||||||
|
; Delays in cycles, milliseconds, etc.
|
||||||
|
|
||||||
|
; All routines are re-entrant (no global data). Routines never
|
||||||
|
; touch BC, DE, or HL registers. These ASSUME CPU is at normal
|
||||||
|
; speed. If running at double speed, msec/usec delays are half advertised.
|
||||||
|
|
||||||
|
; Delays n cycles, from 0 to 16777215
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro delay ARGS n
|
||||||
|
.if n < 0
|
||||||
|
.printt "Delay must be >= 0"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
.if n > 16777215
|
||||||
|
.printt "Delay must be < 16777216"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
delay_ n&$FFFF, n>>16
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Delays n clocks, from 0 to 16777216*4. Must be multiple of 4.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro delay_clocks ARGS n
|
||||||
|
.if n # 4 != 0
|
||||||
|
.printt "Delay must be a multiple of 4"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
delay_ (n/4)&$FFFF,(n/4)>>16
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Delays n microseconds (1/1000000 second)
|
||||||
|
; n can range from 0 to 4000 usec.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro delay_usec ARGS n
|
||||||
|
.if n < 0
|
||||||
|
.printt "Delay must be >= 0"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
.if n > 4000
|
||||||
|
.printt "Delay must be <= 4000 usec"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
delay_ ((n * 1048576 + 500000) / 1000000)&$FFFF,((n * 1048576 + 500000) / 1000000)>>16
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Delays n milliseconds (1/1000 second)
|
||||||
|
; n can range from 0 to 10000 msec.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro delay_msec ARGS n
|
||||||
|
.if n < 0
|
||||||
|
.printt "Delay must be >= 0"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
.if n > 10000
|
||||||
|
.printt "Delay must be <= 10000 msec"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
delay_ ((n * 1048576 + 500) / 1000)&$FFFF, ((n * 1048576 + 500) / 1000)>>16
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; All the low/high quantities are to deal wla-dx's asinine
|
||||||
|
; restriction full expressions must evaluate to a 16-bit
|
||||||
|
; value. If the author ever rectifies this, all "high"
|
||||||
|
; arguments can be treated as zero and removed. Better yet,
|
||||||
|
; I'll just find an assembler that didn't crawl out of
|
||||||
|
; the sewer (this is one of too many bugs I've wasted
|
||||||
|
; hours working around).
|
||||||
|
|
||||||
|
.define max_short_delay 28
|
||||||
|
|
||||||
|
.macro delay_long_ ARGS n, high
|
||||||
|
; 0+ to avoid assembler treating as memory read
|
||||||
|
ld a,0+(((high<<16)+n) - 11) >> 16
|
||||||
|
call delay_65536a_9_cycles_
|
||||||
|
delay_nosave_ (((high<<16)+n) - 11)&$FFFF, 0
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Doesn't save AF, allowing minimization of AF save/restore
|
||||||
|
.macro delay_nosave_ ARGS n, high
|
||||||
|
; 65536+11 = maximum delay using delay_256a_9_cycles_
|
||||||
|
; 255+22 = maximum delay using delay_a_20_cycles
|
||||||
|
; 22 = minimum delay using delay_a_20_cycles
|
||||||
|
.if high > 1
|
||||||
|
delay_long_ n, high
|
||||||
|
.else
|
||||||
|
.if high*n > 11
|
||||||
|
delay_long_ n, high
|
||||||
|
.else
|
||||||
|
.if (high*(255+22+1))|n > 255+22
|
||||||
|
ld a,>(((high<<16)+n) - 11)
|
||||||
|
call delay_256a_9_cycles_
|
||||||
|
delay_nosave_ <(((high<<16)+n) - 11), 0
|
||||||
|
.else
|
||||||
|
.if n >= 22
|
||||||
|
ld a,n - 22
|
||||||
|
call delay_a_20_cycles
|
||||||
|
.else
|
||||||
|
delay_short_ n
|
||||||
|
.endif
|
||||||
|
.endif
|
||||||
|
.endif
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro delay_ ARGS low, high
|
||||||
|
.if (high*(max_short_delay+1))|low > max_short_delay
|
||||||
|
push af
|
||||||
|
delay_nosave_ ((high<<16)+low - 7)&$FFFF, ((high<<16)+low - 7)>>16
|
||||||
|
pop af
|
||||||
|
.else
|
||||||
|
delay_short_ low
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
|
||||||
|
; Delays A cycles + overhead
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
; Time: A+20 cycles (including CALL)
|
||||||
|
delay_a_20_cycles:
|
||||||
|
- sub 5 ; 2
|
||||||
|
jr nc,- ;3/2 do multiples of 5
|
||||||
|
rra ; 1
|
||||||
|
jr nc,+ ;3/2 bit 0
|
||||||
|
+ adc 1 ; 2
|
||||||
|
ret nc ;5/2 -1: 0 cycles
|
||||||
|
ret z ;5/2 0: 2 cycles
|
||||||
|
nop ; 1 1: 4 cycles
|
||||||
|
ret ; 4 (thanks to dclxvi for original algorithm)
|
||||||
|
|
||||||
|
; Delays A*256 cycles + overhead
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
; Time: A*256+12 cycles (including CALL)
|
||||||
|
delay_256a_12_cycles:
|
||||||
|
or a ; 1
|
||||||
|
ret z ; 5/2
|
||||||
|
delay_256a_9_cycles_:
|
||||||
|
- delay 256-4
|
||||||
|
dec a ; 1
|
||||||
|
jr nz,- ;3/2
|
||||||
|
ret ; 4
|
||||||
|
|
||||||
|
; Delays A*65536 cycles + overhead
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
; Time: A*65536+12 cycles (including CALL)
|
||||||
|
delay_65536a_12_cycles:
|
||||||
|
or a ; 1
|
||||||
|
ret z ;5/2
|
||||||
|
delay_65536a_9_cycles_:
|
||||||
|
- delay 65536-4
|
||||||
|
dec a ; 1
|
||||||
|
jr nz,- ;3/2
|
||||||
|
ret ; 4
|
||||||
|
|
||||||
|
; Delays H*256+L cycles + overhead
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
; Time: H*256+L+51 cycles
|
||||||
|
delay_hl_51_cycles:
|
||||||
|
push af
|
||||||
|
ld a,h
|
||||||
|
call delay_256a_12_cycles
|
||||||
|
ld a,l
|
||||||
|
call delay_a_20_cycles
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
; delay_short_ macro calls into these
|
||||||
|
.ds max_short_delay-10,$00 ; NOP repeated several times
|
||||||
|
delay_unrolled_:
|
||||||
|
ret
|
||||||
|
|
||||||
|
.macro delay_short_ ARGS n
|
||||||
|
.if n < 0
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
.if n > max_short_delay
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.if n == 1
|
||||||
|
nop
|
||||||
|
.endif
|
||||||
|
.if n == 2
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
.endif
|
||||||
|
.if n == 3
|
||||||
|
.byte $18,$00 ; JR +0
|
||||||
|
.endif
|
||||||
|
.if n == 4
|
||||||
|
.byte $18,$00 ; JR +0
|
||||||
|
nop
|
||||||
|
.endif
|
||||||
|
.if n == 5
|
||||||
|
.byte $18,$00 ; JR +0
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
.endif
|
||||||
|
.if n == 6
|
||||||
|
.byte $18,$00 ; JR +0
|
||||||
|
.byte $18,$00 ; JR +0
|
||||||
|
.endif
|
||||||
|
.if n == 7
|
||||||
|
push af
|
||||||
|
pop af
|
||||||
|
.endif
|
||||||
|
.if n == 8
|
||||||
|
push af
|
||||||
|
pop af
|
||||||
|
nop
|
||||||
|
.endif
|
||||||
|
.if n == 9
|
||||||
|
push af
|
||||||
|
pop af
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
.endif
|
||||||
|
.if n >= 10
|
||||||
|
call delay_unrolled_ + 10 - n
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
; Game Boy hardware addresses
|
||||||
|
|
||||||
|
; $0000-$3FFF Fixed ROM bank
|
||||||
|
; $4000-$7FFF Switchable bank
|
||||||
|
; $8000-$9FFF VRAM
|
||||||
|
; $A000-$BFFF optional cartridge RAM
|
||||||
|
; $C000-$DFFF RAM
|
||||||
|
; $E000-$FDFF RAM mirror
|
||||||
|
; $FE00-$FE9F OAM
|
||||||
|
; $FEA0-$FEFF unused
|
||||||
|
; $FF00-$FF7F registers
|
||||||
|
; $FF80-$FFFE RAM
|
||||||
|
; $FFFF register
|
||||||
|
|
||||||
|
; Memory
|
||||||
|
.define VRAM $8000 ; video memory
|
||||||
|
.define TILES $8000 ; tile images
|
||||||
|
.define BGMAP0 $9800 ; first 32x32 tilemap
|
||||||
|
.define BGMAP1 $9C00 ; second 32x32 tilemap
|
||||||
|
.define BRAM $A000 ; cart memory
|
||||||
|
.define WRAM $C000 ; internal memory
|
||||||
|
.define OAM $FE00 ; sprite memory
|
||||||
|
.define HRAM $FF80 ; fast memory for LDH
|
||||||
|
|
||||||
|
; Registers
|
||||||
|
|
||||||
|
.define RAMEN $0000 ; cartridge WRAM control
|
||||||
|
.define BANK $2000 ; bank select
|
||||||
|
.define P1 $FF00 ; controller
|
||||||
|
|
||||||
|
; Game link I/O
|
||||||
|
.define SB $FF01 ; serial buffer
|
||||||
|
.define SC $FF02 ; serial control
|
||||||
|
|
||||||
|
; Interrupts
|
||||||
|
.define DIV $FF04
|
||||||
|
.define TIMA $FF05
|
||||||
|
.define TMA $FF06
|
||||||
|
.define TAC $FF07
|
||||||
|
.define IF $FF0F
|
||||||
|
.define IE $FFFF
|
||||||
|
|
||||||
|
; LCD registers
|
||||||
|
.define LCDC $FF40 ; control
|
||||||
|
.define STAT $FF41 ; status
|
||||||
|
.define SCY $FF42 ; scroll Y
|
||||||
|
.define SCX $FF43 ; scroll X
|
||||||
|
.define LY $FF44 ; current Y being rendered
|
||||||
|
.define BGP $FF47
|
||||||
|
|
||||||
|
.define KEY1 $FF4D ; for changing CPU speed
|
||||||
|
.define VBK $FF4F
|
||||||
|
|
||||||
|
; Sound registers
|
||||||
|
.define NR10 $FF10
|
||||||
|
.define NR11 $FF11
|
||||||
|
.define NR12 $FF12
|
||||||
|
.define NR13 $FF13
|
||||||
|
.define NR14 $FF14
|
||||||
|
|
||||||
|
.define NR21 $FF16
|
||||||
|
.define NR22 $FF17
|
||||||
|
.define NR23 $FF18
|
||||||
|
.define NR24 $FF19
|
||||||
|
|
||||||
|
.define NR30 $FF1A
|
||||||
|
.define NR31 $FF1B
|
||||||
|
.define NR32 $FF1C
|
||||||
|
.define NR33 $FF1D
|
||||||
|
.define NR34 $FF1E
|
||||||
|
|
||||||
|
.define NR41 $FF20
|
||||||
|
.define NR42 $FF21
|
||||||
|
.define NR43 $FF22
|
||||||
|
.define NR44 $FF23
|
||||||
|
|
||||||
|
.define NR50 $FF24
|
||||||
|
.define NR51 $FF25
|
||||||
|
.define NR52 $FF26
|
||||||
|
|
||||||
|
.define WAVE $FF30
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
; General macros
|
||||||
|
|
||||||
|
; Reads A from addr, from $FF00 to $FFFF
|
||||||
|
; Preserved: F, BC, DE, HL
|
||||||
|
; Time: 3 cycles
|
||||||
|
.macro lda ; addr
|
||||||
|
ldh a,(\1 - $FF00)
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Writes A to addr, from $FF00 to $FFFF
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
; Time: 3 cycles
|
||||||
|
.macro sta ; addr
|
||||||
|
ldh (\1 - $FF00),a
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Writes immediate data to addr, from $FF00 to $FFFF
|
||||||
|
; Preserved: F, BC, DE, HL
|
||||||
|
; Time: 5 cycles
|
||||||
|
.macro wreg ARGS addr, data
|
||||||
|
ld a,data
|
||||||
|
sta addr
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Writes byte to addr
|
||||||
|
; Preserved: F, BC, DE, HL
|
||||||
|
; Time: 6 cycles
|
||||||
|
.macro setb ; addr, data
|
||||||
|
ld a,\2
|
||||||
|
ld (\1),a
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Writes word to addr
|
||||||
|
; Preserved: F, BC, DE, HL
|
||||||
|
; Time: 12 cycles
|
||||||
|
.macro setw ; addr, data
|
||||||
|
ld a,<\2
|
||||||
|
ld (\1),a
|
||||||
|
ld a,>\2
|
||||||
|
ld (\1+1),a
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Calls routine multiple times, with A having the
|
||||||
|
; value 'start' the first time, 'start+step' the
|
||||||
|
; second time, up to 'end' for the last time.
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
.macro for_loop ; routine,start,end,step
|
||||||
|
ld a,\2
|
||||||
|
|
||||||
|
for_loop\@:
|
||||||
|
push af
|
||||||
|
call \1
|
||||||
|
pop af
|
||||||
|
|
||||||
|
add \4
|
||||||
|
cp <(\3 + \4)
|
||||||
|
jr nz,for_loop\@
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Calls routine n times. The value of A in the routine
|
||||||
|
; counts from 0 to n-1.
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
.macro loop_n_times ; routine,n
|
||||||
|
for_loop \1,0,\2 - 1,+1
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Same as for_loop, but counts with 16-bit value in BC.
|
||||||
|
; Preserved: DE, HL
|
||||||
|
.macro for_loop16 ; routine,start,end,step
|
||||||
|
ld bc,\2
|
||||||
|
|
||||||
|
for_loop16\@:
|
||||||
|
push bc
|
||||||
|
call \1
|
||||||
|
pop bc
|
||||||
|
|
||||||
|
ld a,c
|
||||||
|
add <\4
|
||||||
|
ld c,a
|
||||||
|
|
||||||
|
ld a,b
|
||||||
|
adc >\4
|
||||||
|
ld b,a
|
||||||
|
|
||||||
|
cp >(\3+\4)
|
||||||
|
jr nz,for_loop16\@
|
||||||
|
|
||||||
|
ld a,c
|
||||||
|
cp <(\3+\4)
|
||||||
|
jr nz,for_loop16\@
|
||||||
|
.endm
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
; Printing of numeric values
|
||||||
|
|
||||||
|
; Prints value of indicated register/pair
|
||||||
|
; as 2/4 hex digits, followed by a space.
|
||||||
|
; Updates checksum with printed values.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
|
||||||
|
print_regs:
|
||||||
|
call print_af
|
||||||
|
call print_bc
|
||||||
|
call print_de
|
||||||
|
call print_hl
|
||||||
|
call print_newline
|
||||||
|
ret
|
||||||
|
|
||||||
|
print_a:
|
||||||
|
push af
|
||||||
|
print_a_:
|
||||||
|
call print_hex
|
||||||
|
ld a,' '
|
||||||
|
call print_char_nocrc
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
print_af:
|
||||||
|
push af
|
||||||
|
call print_hex
|
||||||
|
pop af
|
||||||
|
print_f:
|
||||||
|
push bc
|
||||||
|
push af
|
||||||
|
pop bc
|
||||||
|
call print_c
|
||||||
|
pop bc
|
||||||
|
ret
|
||||||
|
|
||||||
|
print_b:
|
||||||
|
push af
|
||||||
|
ld a,b
|
||||||
|
jr print_a_
|
||||||
|
|
||||||
|
print_c:
|
||||||
|
push af
|
||||||
|
ld a,c
|
||||||
|
jr print_a_
|
||||||
|
|
||||||
|
print_d:
|
||||||
|
push af
|
||||||
|
ld a,d
|
||||||
|
jr print_a_
|
||||||
|
|
||||||
|
print_e:
|
||||||
|
push af
|
||||||
|
ld a,e
|
||||||
|
jr print_a_
|
||||||
|
|
||||||
|
print_h:
|
||||||
|
push af
|
||||||
|
ld a,h
|
||||||
|
jr print_a_
|
||||||
|
|
||||||
|
print_l:
|
||||||
|
push af
|
||||||
|
ld a,l
|
||||||
|
jr print_a_
|
||||||
|
|
||||||
|
print_bc:
|
||||||
|
push af
|
||||||
|
push bc
|
||||||
|
print_bc_:
|
||||||
|
ld a,b
|
||||||
|
call print_hex
|
||||||
|
ld a,c
|
||||||
|
pop bc
|
||||||
|
jr print_a_
|
||||||
|
|
||||||
|
print_de:
|
||||||
|
push af
|
||||||
|
push bc
|
||||||
|
ld b,d
|
||||||
|
ld c,e
|
||||||
|
jr print_bc_
|
||||||
|
|
||||||
|
print_hl:
|
||||||
|
push af
|
||||||
|
push bc
|
||||||
|
ld b,h
|
||||||
|
ld c,l
|
||||||
|
jr print_bc_
|
||||||
|
|
||||||
|
|
||||||
|
; Prints A as two hex chars and updates checksum
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
print_hex:
|
||||||
|
call update_crc
|
||||||
|
print_hex_nocrc:
|
||||||
|
push af
|
||||||
|
swap a
|
||||||
|
call +
|
||||||
|
pop af
|
||||||
|
|
||||||
|
+ and $0F
|
||||||
|
cp 10
|
||||||
|
jr c,+
|
||||||
|
add 7
|
||||||
|
+ add '0'
|
||||||
|
jp print_char_nocrc
|
||||||
|
|
||||||
|
|
||||||
|
; Prints char_nz if Z flag is clear,
|
||||||
|
; char_z if Z flag is set.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro print_nz ARGS char_nz, char_z
|
||||||
|
push af
|
||||||
|
ld a,char_nz
|
||||||
|
jr nz,print_nz\@
|
||||||
|
ld a,char_z
|
||||||
|
print_nz\@:
|
||||||
|
call print_char
|
||||||
|
pop af
|
||||||
|
.endm
|
||||||
|
|
||||||
|
|
||||||
|
; Prints char_nc if C flag is clear,
|
||||||
|
; char_c if C flag is set.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro print_nc ARGS char_nc, char_c
|
||||||
|
push af
|
||||||
|
ld a,char_nc
|
||||||
|
jr nz,print_nc\@
|
||||||
|
ld a,char_c
|
||||||
|
print_nc\@:
|
||||||
|
call print_char
|
||||||
|
pop af
|
||||||
|
.endm
|
||||||
|
|
||||||
|
|
||||||
|
; Prints A as 2 decimal digits
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
print_dec2:
|
||||||
|
push af
|
||||||
|
push bc
|
||||||
|
jr +
|
||||||
|
|
||||||
|
|
||||||
|
; Prints A as 1-3 digit decimal value
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
print_dec:
|
||||||
|
push af
|
||||||
|
push bc
|
||||||
|
|
||||||
|
cp 10
|
||||||
|
jr c,++
|
||||||
|
ld c,100
|
||||||
|
cp c
|
||||||
|
call nc,@digit
|
||||||
|
+ ld c,10
|
||||||
|
call @digit
|
||||||
|
++ add '0'
|
||||||
|
call print_char
|
||||||
|
|
||||||
|
pop bc
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
@digit:
|
||||||
|
ld b,'0'-1
|
||||||
|
- inc b
|
||||||
|
sub c
|
||||||
|
jr nc,-
|
||||||
|
add c
|
||||||
|
|
||||||
|
ld c,a
|
||||||
|
ld a,b
|
||||||
|
call print_char
|
||||||
|
ld a,c
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
; Main printing routine that checksums and
|
||||||
|
; prints to output device
|
||||||
|
|
||||||
|
; Character that does equivalent of print_newline
|
||||||
|
.define newline 10
|
||||||
|
|
||||||
|
; Prints char without updating checksum
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
;print_char_nocrc (defined by user)
|
||||||
|
|
||||||
|
|
||||||
|
; Prints character and updates checksum UNLESS
|
||||||
|
; it's a newline.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
print_char:
|
||||||
|
push af
|
||||||
|
cp newline
|
||||||
|
call nz,update_crc
|
||||||
|
call print_char_nocrc
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Prints space. Does NOT update checksum.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
print_space:
|
||||||
|
push af
|
||||||
|
ld a,' '
|
||||||
|
call print_char_nocrc
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Advances to next line. Does NOT update checksum.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
print_newline:
|
||||||
|
push af
|
||||||
|
ld a,newline
|
||||||
|
call print_char_nocrc
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Prints immediate string
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro print_str ; string,string2
|
||||||
|
push hl
|
||||||
|
call print_str_
|
||||||
|
.byte \1
|
||||||
|
.if NARGS > 1
|
||||||
|
.byte \2
|
||||||
|
.endif
|
||||||
|
.if NARGS > 2
|
||||||
|
.byte \3
|
||||||
|
.endif
|
||||||
|
.byte 0
|
||||||
|
pop hl
|
||||||
|
.endm
|
||||||
|
|
||||||
|
print_str_:
|
||||||
|
pop hl
|
||||||
|
call print_str_hl
|
||||||
|
jp hl
|
||||||
|
|
||||||
|
|
||||||
|
; Prints zero-terminated string pointed to by HL.
|
||||||
|
; On return, HL points to byte AFTER zero terminator.
|
||||||
|
; Preserved: AF, BC, DE
|
||||||
|
print_str_hl:
|
||||||
|
push af
|
||||||
|
jr +
|
||||||
|
- call print_char
|
||||||
|
+ ldi a,(hl)
|
||||||
|
or a
|
||||||
|
jr nz,-
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,261 @@
|
||||||
|
; Common routines and runtime
|
||||||
|
|
||||||
|
.define RUNTIME_INCLUDED 1
|
||||||
|
|
||||||
|
; A few bytes of RAM that aren't cleared
|
||||||
|
.define nv_ram_base $D800
|
||||||
|
.define nv_ram nv_ram_base
|
||||||
|
|
||||||
|
; Address of next normal variable
|
||||||
|
.define bss_base nv_ram_base+$80
|
||||||
|
.define bss bss_base
|
||||||
|
|
||||||
|
; Address of next direct-page ($FFxx) variable
|
||||||
|
.define dp_base $FF80
|
||||||
|
.define dp dp_base
|
||||||
|
|
||||||
|
; Top of stack
|
||||||
|
.define std_stack $DFFF+1
|
||||||
|
|
||||||
|
; Final exit result byte is written here
|
||||||
|
.define final_result $A000
|
||||||
|
|
||||||
|
; Text output is written here as zero-terminated string
|
||||||
|
.define text_out_base $A004
|
||||||
|
|
||||||
|
; DMG/CGB hardware identifier
|
||||||
|
.define gb_id_cgb $10 ; mask for testing CGB bit
|
||||||
|
.define gb_id_devcart $04 ; mask for testing "on devcart" bit
|
||||||
|
.define gb_id nv_ram
|
||||||
|
.redefine nv_ram nv_ram+1
|
||||||
|
|
||||||
|
; Copies C*$100 bytes from HL to $C000, then jumps to it.
|
||||||
|
; A is preserved for jumped-to code.
|
||||||
|
copy_to_wram_then_run:
|
||||||
|
ld b,a
|
||||||
|
|
||||||
|
ld de,$C000
|
||||||
|
- ld a,(hl+)
|
||||||
|
ld (de),a
|
||||||
|
inc e
|
||||||
|
jr nz,-
|
||||||
|
inc d
|
||||||
|
dec c
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
ld a,b
|
||||||
|
jp $C000
|
||||||
|
|
||||||
|
|
||||||
|
.ifndef RST_OFFSET
|
||||||
|
.define RST_OFFSET 0
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.ifndef CUSTOM_RESET
|
||||||
|
reset:
|
||||||
|
di
|
||||||
|
|
||||||
|
; Run code from $C000, as is done on devcart. This
|
||||||
|
; ensures minimal difference in how it behaves.
|
||||||
|
ld hl,$4000
|
||||||
|
ld c,$14
|
||||||
|
jp copy_to_wram_then_run
|
||||||
|
|
||||||
|
.bank 1 slot 1
|
||||||
|
.org 0
|
||||||
|
jp std_reset
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; returnOrg puts this code AFTER user code.
|
||||||
|
.section "runtime" returnOrg
|
||||||
|
|
||||||
|
; Catch user code running off end
|
||||||
|
jp internal_error
|
||||||
|
|
||||||
|
; Common routines
|
||||||
|
.include "gb.inc"
|
||||||
|
.include "macros.inc"
|
||||||
|
.include "delay.s"
|
||||||
|
.include "crc.s"
|
||||||
|
.include "printing.s"
|
||||||
|
.include "numbers.s"
|
||||||
|
.include "testing.s"
|
||||||
|
|
||||||
|
; Sets up hardware and runs main
|
||||||
|
std_reset:
|
||||||
|
|
||||||
|
; Init hardware
|
||||||
|
di
|
||||||
|
ld sp,std_stack
|
||||||
|
|
||||||
|
; Save DMG/CGB id
|
||||||
|
ld (gb_id),a
|
||||||
|
|
||||||
|
; Clear memory except very top of stack
|
||||||
|
ld bc,std_stack-bss_base - 2
|
||||||
|
ld hl,bss_base
|
||||||
|
call clear_mem
|
||||||
|
ld bc,$FFFF-dp_base
|
||||||
|
ld hl,dp_base
|
||||||
|
call clear_mem
|
||||||
|
|
||||||
|
; Init hardware
|
||||||
|
wreg TAC,$00
|
||||||
|
wreg IF,$00
|
||||||
|
wreg IE,$00
|
||||||
|
|
||||||
|
wreg NR52,0 ; sound off
|
||||||
|
wreg NR52,$80 ; sound on
|
||||||
|
wreg NR51,$FF ; mono
|
||||||
|
wreg NR50,$77 ; volume
|
||||||
|
|
||||||
|
call init_runtime
|
||||||
|
call init_text_out
|
||||||
|
call console_init
|
||||||
|
call init_testing
|
||||||
|
|
||||||
|
.ifdef TEST_NAME
|
||||||
|
print_str TEST_NAME,newline,newline
|
||||||
|
.endif
|
||||||
|
|
||||||
|
call reset_crc ; in case init_runtime prints anything
|
||||||
|
|
||||||
|
delay_msec 250
|
||||||
|
|
||||||
|
; Run user code
|
||||||
|
call main
|
||||||
|
|
||||||
|
; Default is to successful exit
|
||||||
|
ld a,0
|
||||||
|
jp exit
|
||||||
|
|
||||||
|
|
||||||
|
; Exits code and reports value of A
|
||||||
|
exit:
|
||||||
|
ld sp,std_stack
|
||||||
|
push af
|
||||||
|
call +
|
||||||
|
call console_show
|
||||||
|
pop af
|
||||||
|
call play_byte
|
||||||
|
jp post_exit
|
||||||
|
|
||||||
|
+ push af
|
||||||
|
call print_newline
|
||||||
|
pop af
|
||||||
|
|
||||||
|
; Report exit status
|
||||||
|
cp 1
|
||||||
|
|
||||||
|
; 0: ""
|
||||||
|
ret c
|
||||||
|
|
||||||
|
; 1: "Failed"
|
||||||
|
jr nz,+
|
||||||
|
print_str "Failed",newline
|
||||||
|
ret
|
||||||
|
|
||||||
|
; n: "Failed #n"
|
||||||
|
+ print_str "Failed #"
|
||||||
|
call print_dec
|
||||||
|
call print_newline
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Clears BC bytes starting at HL
|
||||||
|
clear_mem:
|
||||||
|
; If C>0, increment B
|
||||||
|
dec bc
|
||||||
|
inc c
|
||||||
|
inc b
|
||||||
|
|
||||||
|
ld a,0
|
||||||
|
- ld (hl+),a
|
||||||
|
dec c
|
||||||
|
jr nz,-
|
||||||
|
dec b
|
||||||
|
jr nz,-
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Reports internal error and exits with code 255
|
||||||
|
internal_error:
|
||||||
|
print_str "Internal error"
|
||||||
|
ld a,255
|
||||||
|
jp exit
|
||||||
|
|
||||||
|
|
||||||
|
; build_devcart and build_multi customize this
|
||||||
|
.ifndef CUSTOM_PRINT
|
||||||
|
.define text_out_addr bss+0
|
||||||
|
.redefine bss bss+2
|
||||||
|
|
||||||
|
; Initializes text output to cartridge RAM
|
||||||
|
init_text_out:
|
||||||
|
; Enable cartridge RAM and set text output pointer
|
||||||
|
setb RAMEN,$0A
|
||||||
|
setw text_out_addr,text_out_base
|
||||||
|
setb text_out_base-3,$DE
|
||||||
|
setb text_out_base-2,$B0
|
||||||
|
setb text_out_base-1,$61
|
||||||
|
setb text_out_base,0
|
||||||
|
setb final_result,$80
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Appends character to text output string
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
write_text_out:
|
||||||
|
push hl
|
||||||
|
push af
|
||||||
|
ld a,(text_out_addr)
|
||||||
|
ld l,a
|
||||||
|
ld a,(text_out_addr+1)
|
||||||
|
ld h,a
|
||||||
|
inc hl
|
||||||
|
ld (hl),0
|
||||||
|
ld a,l
|
||||||
|
ld (text_out_addr),a
|
||||||
|
ld a,h
|
||||||
|
ld (text_out_addr+1),a
|
||||||
|
dec hl
|
||||||
|
pop af
|
||||||
|
ld (hl),a
|
||||||
|
pop hl
|
||||||
|
ret
|
||||||
|
|
||||||
|
print_char_nocrc:
|
||||||
|
call write_text_out
|
||||||
|
jp console_print
|
||||||
|
.endif
|
||||||
|
|
||||||
|
|
||||||
|
; only build_rom uses console
|
||||||
|
.ifdef NEED_CONSOLE
|
||||||
|
.include "console.s"
|
||||||
|
.else
|
||||||
|
console_init:
|
||||||
|
console_print:
|
||||||
|
console_flush:
|
||||||
|
console_normal:
|
||||||
|
console_inverse:
|
||||||
|
console_show:
|
||||||
|
console_set_mode:
|
||||||
|
ret
|
||||||
|
.endif
|
||||||
|
|
||||||
|
|
||||||
|
; build_devcart and build_multi need to customize this
|
||||||
|
.ifndef CUSTOM_EXIT
|
||||||
|
post_exit:
|
||||||
|
ld (final_result),a
|
||||||
|
forever:
|
||||||
|
wreg NR52,0 ; sound off
|
||||||
|
- jr -
|
||||||
|
.endif
|
||||||
|
|
||||||
|
|
||||||
|
.macro def_rst ARGS addr
|
||||||
|
.bank 0 slot 0
|
||||||
|
.org addr+RST_OFFSET
|
||||||
|
.endm
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
; Diagnostic and testing utilities
|
||||||
|
|
||||||
|
.define test_code bss+0
|
||||||
|
.define test_name bss+1
|
||||||
|
.redefine bss bss+3
|
||||||
|
|
||||||
|
|
||||||
|
; Sets test code and optional error text.
|
||||||
|
; Takes multiple strings due to wla's idiotic
|
||||||
|
; default limit of 63 chars per string.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro set_test ; code[,text[,text2[,text3]]]
|
||||||
|
push hl
|
||||||
|
call set_test_
|
||||||
|
jr @set_test\@
|
||||||
|
.byte \1
|
||||||
|
.if NARGS > 1
|
||||||
|
.byte \2
|
||||||
|
.endif
|
||||||
|
.if NARGS > 2
|
||||||
|
.byte \3
|
||||||
|
.endif
|
||||||
|
.if NARGS > 3
|
||||||
|
.byte \4
|
||||||
|
.endif
|
||||||
|
.byte 0
|
||||||
|
@set_test\@:
|
||||||
|
pop hl
|
||||||
|
.endm
|
||||||
|
|
||||||
|
set_test_:
|
||||||
|
pop hl
|
||||||
|
push hl
|
||||||
|
push af
|
||||||
|
inc hl
|
||||||
|
inc hl
|
||||||
|
ldi a,(hl)
|
||||||
|
ld (test_code),a
|
||||||
|
ld a,l
|
||||||
|
ld (test_name),a
|
||||||
|
ld a,h
|
||||||
|
ld (test_name+1),a
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Initializes testing module
|
||||||
|
init_testing:
|
||||||
|
set_test $FF
|
||||||
|
call init_crc
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Reports "Passed", then exits with code 0
|
||||||
|
tests_passed:
|
||||||
|
call print_newline
|
||||||
|
print_str "Passed"
|
||||||
|
ld a,0
|
||||||
|
jp exit
|
||||||
|
|
||||||
|
|
||||||
|
; Reports "Done" if set_test has never been used,
|
||||||
|
; "Passed" if set_test 0 was last used, or
|
||||||
|
; failure if set_test n was last used.
|
||||||
|
tests_done:
|
||||||
|
ld a,(test_code)
|
||||||
|
inc a
|
||||||
|
jr z,+
|
||||||
|
dec a
|
||||||
|
jr z,tests_passed
|
||||||
|
jr test_failed
|
||||||
|
+ print_str "Done"
|
||||||
|
ld a,0
|
||||||
|
jp exit
|
||||||
|
|
||||||
|
|
||||||
|
; Reports current error text and exits with result code
|
||||||
|
test_failed:
|
||||||
|
ld a,(test_name)
|
||||||
|
ld l,a
|
||||||
|
ld a,(test_name+1)
|
||||||
|
ld h,a
|
||||||
|
ld a,(hl)
|
||||||
|
or a
|
||||||
|
jr z,+
|
||||||
|
call print_newline
|
||||||
|
call print_str_hl
|
||||||
|
call print_newline
|
||||||
|
+
|
||||||
|
ld a,(test_code)
|
||||||
|
cp $FF ; if a = $FF then a = 1
|
||||||
|
jr nz,+
|
||||||
|
ld a,1
|
||||||
|
+ jp exit
|
||||||
|
|
||||||
|
|
||||||
|
; Prints checksum as 8-character hex value
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
print_crc:
|
||||||
|
push af
|
||||||
|
|
||||||
|
; Must read checksum entirely before printing,
|
||||||
|
; since printing updates it.
|
||||||
|
lda checksum
|
||||||
|
cpl
|
||||||
|
push af
|
||||||
|
|
||||||
|
lda checksum+1
|
||||||
|
cpl
|
||||||
|
push af
|
||||||
|
|
||||||
|
lda checksum+2
|
||||||
|
cpl
|
||||||
|
push af
|
||||||
|
|
||||||
|
lda checksum+3
|
||||||
|
cpl
|
||||||
|
|
||||||
|
call print_hex
|
||||||
|
pop af
|
||||||
|
call print_hex
|
||||||
|
pop af
|
||||||
|
call print_hex
|
||||||
|
pop af
|
||||||
|
call print_a
|
||||||
|
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; If checksum doesn't match expected, reports failed test.
|
||||||
|
; Passing 0 just prints checksum. Clears checksum afterwards.
|
||||||
|
.macro check_crc ARGS crc
|
||||||
|
.if crc == 0
|
||||||
|
call print_newline
|
||||||
|
call print_crc
|
||||||
|
.else
|
||||||
|
ld bc,(crc >> 16) ~ $FFFF
|
||||||
|
ld de,(crc & $FFFF) ~ $FFFF
|
||||||
|
call check_crc_
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Checks CRC, differing based on DMG or CGB build
|
||||||
|
.macro check_crc_dmg_cgb ARGS dmg, cgb
|
||||||
|
.ifdef REQUIRE_DMG
|
||||||
|
check_crc dmg
|
||||||
|
.else
|
||||||
|
.ifdef REQUIRE_CGB
|
||||||
|
check_crc cgb
|
||||||
|
.else
|
||||||
|
.printt "CGB or DMG must be specified"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
check_crc_:
|
||||||
|
lda checksum+0
|
||||||
|
cp e
|
||||||
|
jr nz,+
|
||||||
|
|
||||||
|
lda checksum+1
|
||||||
|
cp d
|
||||||
|
jr nz,+
|
||||||
|
|
||||||
|
lda checksum+2
|
||||||
|
cp c
|
||||||
|
jr nz,+
|
||||||
|
|
||||||
|
lda checksum+3
|
||||||
|
cp b
|
||||||
|
jr nz,+
|
||||||
|
|
||||||
|
jp reset_crc
|
||||||
|
|
||||||
|
+ call print_crc
|
||||||
|
jp test_failed
|
||||||
|
|
||||||
|
|
||||||
|
; Updates checksum with bytes from addr to addr+size-1
|
||||||
|
.macro checksum_mem ARGS addr,size
|
||||||
|
ld hl,addr
|
||||||
|
ld bc,size
|
||||||
|
call checksum_mem_
|
||||||
|
.endm
|
||||||
|
|
||||||
|
checksum_mem_:
|
||||||
|
- ldi a,(hl)
|
||||||
|
call update_crc
|
||||||
|
dec bc
|
||||||
|
ld a,b
|
||||||
|
or c
|
||||||
|
jr nz,-
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
[objects]
|
||||||
|
test.o
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
Game Boy Tests Source Code
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Building with wla-dx
|
||||||
|
--------------------
|
||||||
|
To assemble a test ROM with wla-dx, use the following commands:
|
||||||
|
|
||||||
|
wla -o source_filename_here.s test.o
|
||||||
|
wlalink linkfile test.gb
|
||||||
|
|
||||||
|
To assemble as a GBS music file:
|
||||||
|
|
||||||
|
wla -o source_filename_here.s test.o -DBUILD_GBS
|
||||||
|
wlalink linkfile test.gbs
|
||||||
|
|
||||||
|
Note that some tests might only work when built as a ROM or GBS file,
|
||||||
|
but not both.
|
||||||
|
|
||||||
|
Some tests might include a ROM/GBS that has all the tests combined.
|
||||||
|
Building such a multi-test is complex and the necessary files aren't
|
||||||
|
included.
|
||||||
|
|
||||||
|
|
||||||
|
Framework
|
||||||
|
---------
|
||||||
|
Each test is in a single source file, and makes use of several library
|
||||||
|
source files from common/. This framework provides common services and
|
||||||
|
reduces code to only that which performs the actual test. Virtually all
|
||||||
|
tests include "shell.inc" at the beginning, which sets things up and
|
||||||
|
includes all the appropriate library files.
|
||||||
|
|
||||||
|
The reset handler does minimal GB hardware initialization, clears RAM,
|
||||||
|
sets up the text console, then runs main. Main can exit by returning or
|
||||||
|
jumping to "exit" with an error code in A. Exit reports the code then
|
||||||
|
goes into an infinite loop. If the code is 0, it doesn't do anything,
|
||||||
|
otherwise it reports the code. Code 1 is reported as "Failed", and the
|
||||||
|
rest as "Error <code>".
|
||||||
|
|
||||||
|
The default is to build a ROM. Defining BUILD_GBS will build as an GBS.
|
||||||
|
The other build types aren't supported due to their complexity. I load
|
||||||
|
the code into RAM at $C000 since my devcart requires it, and I don't
|
||||||
|
want the normal ROM to differ in any way from what I've tested. This
|
||||||
|
also allows easy self-modifying code.
|
||||||
|
|
||||||
|
Several routines are available to print values and text to the console.
|
||||||
|
Most update a running CRC-32 checksum which can be checked with
|
||||||
|
check_crc, allowing ALL the output to be checked very easily. If the
|
||||||
|
checksum doesn't match, it is printed, so you can run the code on a GB
|
||||||
|
and paste the correct checksum into your code.
|
||||||
|
|
||||||
|
|
||||||
|
Macros
|
||||||
|
------
|
||||||
|
Some macros are used to make common operations more convenient. The left
|
||||||
|
is equivalent to the right:
|
||||||
|
|
||||||
|
Macro Equivalent
|
||||||
|
-------------------------------------
|
||||||
|
lda addr ldh a,(addr-$FF00)
|
||||||
|
|
||||||
|
sta addr ldh (addr-$FF00),a
|
||||||
|
|
||||||
|
wreg addr,data ld a,data
|
||||||
|
ldh (addr-$FF00),a
|
||||||
|
|
||||||
|
setb ld a,data
|
||||||
|
ld (addr),a
|
||||||
|
|
||||||
|
setw setb addr+0,<data
|
||||||
|
setb addr+1,>data
|
||||||
|
|
||||||
|
for_loop routine,begin,end,step
|
||||||
|
calls routine with A set to successive values
|
||||||
|
|
||||||
|
loop_n_times routine,count
|
||||||
|
calls routine with A from 0 to count-1
|
||||||
|
|
||||||
|
print_str "str" prints string
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
Shay Green <gblargg@gmail.com>
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
; Included at beginning of all programs
|
||||||
|
; that use standard shell
|
||||||
|
|
||||||
|
; Get include files from common/
|
||||||
|
.incdir "common"
|
||||||
|
|
||||||
|
; Sub-test in a multi-test ROM
|
||||||
|
.ifdef BUILD_MULTI
|
||||||
|
.include "build_multi.s"
|
||||||
|
.else
|
||||||
|
|
||||||
|
; GBS music file
|
||||||
|
.ifdef BUILD_GBS
|
||||||
|
.include "build_gbs.s"
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; Devcart
|
||||||
|
.ifdef BUILD_DEVCART
|
||||||
|
.include "build_devcart.s"
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; GB ROM (default)
|
||||||
|
.ifndef RUNTIME_INCLUDED
|
||||||
|
.include "build_rom.s"
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.endif ; .ifdef BUILD_MULTI
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,119 @@
|
||||||
|
Game Boy CPU Instruction Behavior Test
|
||||||
|
--------------------------------------
|
||||||
|
This ROM tests the behavior of all CPU instructions except STOP and the
|
||||||
|
11 illegal opcodes. The tests are fairly thorough, running instructions
|
||||||
|
with boundary data and verifying both the result and that other
|
||||||
|
registers are not modified. Instructions which perform the same
|
||||||
|
operation on different registers are each tested just as thoroughly, in
|
||||||
|
case an emulator implements each independently. Some sub-tests take half
|
||||||
|
minute to complete.
|
||||||
|
|
||||||
|
Failed instructions are listed as
|
||||||
|
|
||||||
|
[CB] opcode
|
||||||
|
|
||||||
|
Some errors cannot of course be diagnosed properly, since the test
|
||||||
|
framework itself relies on basic instruction behavior being correct.
|
||||||
|
|
||||||
|
|
||||||
|
Internal operation
|
||||||
|
------------------
|
||||||
|
The main tests use a framework that runs each instruction in a loop,
|
||||||
|
varying the register values on input and examining them on output.
|
||||||
|
Rather than keep a table of correct values, it simply calculates a
|
||||||
|
CRC-32 checksum of all the output, then compares this with the correct
|
||||||
|
value. Instructions are divided into several groups, each with a
|
||||||
|
different set of input values suited for their behavior; for example,
|
||||||
|
the bit test instructions are fed $01, $02, $04 ... $40, $80, to ensure
|
||||||
|
each bit is handled properly, while the arithmetic instructions are fed
|
||||||
|
$01, $0F, $10, $7F, $FF, to exercise carry and half-carry. A few
|
||||||
|
instructions require a custom test due to their uniqueness.
|
||||||
|
|
||||||
|
|
||||||
|
Multi-ROM
|
||||||
|
---------
|
||||||
|
In the main directory is a single ROM which runs all the tests. It
|
||||||
|
prints a test's number, runs the test, then "ok" if it passes, otherwise
|
||||||
|
a failure code. Once all tests have completed it either reports that all
|
||||||
|
tests passed, or prints the number of failed tests. Finally, it makes
|
||||||
|
several beeps. If a test fails, it can be run on its own by finding the
|
||||||
|
corresponding ROM in individual/.
|
||||||
|
|
||||||
|
Ths compact format on screen is to avoid having the results scroll off
|
||||||
|
the top, so the test can be started and allowed to run without having to
|
||||||
|
constantly monitor the display.
|
||||||
|
|
||||||
|
Currently there is no well-defined way for an emulator test rig to
|
||||||
|
programatically find the result of the test; contact me if you're trying
|
||||||
|
to do completely automated testing of your emulator. One simple approach
|
||||||
|
is to take a screenshot after all tests have run, or even just a
|
||||||
|
checksum of one, and compare this with a previous run.
|
||||||
|
|
||||||
|
|
||||||
|
Failure codes
|
||||||
|
-------------
|
||||||
|
Failed tests may print a failure code, and also short description of the
|
||||||
|
problem. For more information about a failure code, look in the
|
||||||
|
corresponding source file in source/; the point in the code where
|
||||||
|
"set_test n" occurs is where that failure code will be generated.
|
||||||
|
Failure code 1 is a general failure of the test; any further information
|
||||||
|
will be printed.
|
||||||
|
|
||||||
|
Note that once a sub-test fails, no further tests for that file are run.
|
||||||
|
|
||||||
|
|
||||||
|
Console output
|
||||||
|
--------------
|
||||||
|
Information is printed on screen in a way that needs only minimum LCD
|
||||||
|
support, and won't hang if LCD output isn't supported at all.
|
||||||
|
Specifically, while polling LY to wait for vblank, it will time out if
|
||||||
|
it takes too long, so LY always reading back as the same value won't
|
||||||
|
hang the test. It's also OK if scrolling isn't supported; in this case,
|
||||||
|
text will appear starting at the top of the screen.
|
||||||
|
|
||||||
|
Everything printed on screen is also sent to the game link port by
|
||||||
|
writing the character to SB, then writing $81 to SC. This is useful for
|
||||||
|
tests which print lots of information that scrolls off screen.
|
||||||
|
|
||||||
|
|
||||||
|
Source code
|
||||||
|
-----------
|
||||||
|
Source code is included for all tests, in source/. It can be used to
|
||||||
|
build the individual test ROMs. Code for the multi test isn't included
|
||||||
|
due to the complexity of putting everything together.
|
||||||
|
|
||||||
|
Code is written for the wla-dx assembler. To assemble a particular test,
|
||||||
|
execute
|
||||||
|
|
||||||
|
wla -o "source_filename.s" test.o
|
||||||
|
wlalink linkfile test.gb
|
||||||
|
|
||||||
|
Test code uses a common shell framework contained in common/.
|
||||||
|
|
||||||
|
|
||||||
|
Internal framework operation
|
||||||
|
----------------------------
|
||||||
|
Tests use a common framework for setting things up, reporting results,
|
||||||
|
and ending. All files first include "shell.inc", which sets up the ROM
|
||||||
|
header and shell code, and includes other commonly-used modules.
|
||||||
|
|
||||||
|
One oddity is that test code is first copied to internal RAM at $D000,
|
||||||
|
then executed there. This allows self-modification, and ensures the code
|
||||||
|
is executed the same way it is on my devcart, which doesn't have a
|
||||||
|
rewritable ROM as most do.
|
||||||
|
|
||||||
|
Some macros are used to simplify common tasks:
|
||||||
|
|
||||||
|
Macro Behavior
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
wreg addr,data Writes data to addr using LDH
|
||||||
|
lda addr Loads byte from addr into A using LDH
|
||||||
|
sta addr Stores A at addr using LDH
|
||||||
|
delay n Delays n cycles, where NOP = 1 cycle
|
||||||
|
delay_msec n Delays n milliseconds
|
||||||
|
set_test n,"Cause" Sets failure code and optional string
|
||||||
|
|
||||||
|
Routines and macros are documented where they are defined.
|
||||||
|
|
||||||
|
--
|
||||||
|
Shay Green <gblargg@gmail.com>
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
; Tests instructions that don't fit template
|
||||||
|
|
||||||
|
.include "shell.inc"
|
||||||
|
|
||||||
|
main:
|
||||||
|
set_test 2,"JR negative"
|
||||||
|
ld a,0
|
||||||
|
jp jr_neg
|
||||||
|
inc a
|
||||||
|
- inc a
|
||||||
|
inc a
|
||||||
|
cp 2
|
||||||
|
jp nz,test_failed
|
||||||
|
jp +
|
||||||
|
jr_neg:
|
||||||
|
jr -
|
||||||
|
+
|
||||||
|
|
||||||
|
set_test 3,"JR positive"
|
||||||
|
ld a,0
|
||||||
|
jr +
|
||||||
|
inc a
|
||||||
|
+ inc a
|
||||||
|
inc a
|
||||||
|
cp 2
|
||||||
|
jp nz,test_failed
|
||||||
|
|
||||||
|
|
||||||
|
set_test 4,"LD PC,HL"
|
||||||
|
ld hl,+
|
||||||
|
ld a,0
|
||||||
|
ld pc,hl
|
||||||
|
inc a
|
||||||
|
+ inc a
|
||||||
|
inc a
|
||||||
|
cp 2
|
||||||
|
jp nz,test_failed
|
||||||
|
|
||||||
|
|
||||||
|
set_test 5,"POP AF"
|
||||||
|
ld bc,$1200
|
||||||
|
- push bc
|
||||||
|
pop af
|
||||||
|
push af
|
||||||
|
pop de
|
||||||
|
ld a,c
|
||||||
|
and $F0
|
||||||
|
cp e
|
||||||
|
jp nz,test_failed
|
||||||
|
inc b
|
||||||
|
inc c
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
|
||||||
|
set_test 6,"DAA"
|
||||||
|
; Test all combinations of A and flags (256*16 total)
|
||||||
|
ld de,0
|
||||||
|
- push de
|
||||||
|
pop af
|
||||||
|
daa
|
||||||
|
|
||||||
|
push af
|
||||||
|
call update_crc
|
||||||
|
pop hl
|
||||||
|
ld a,l
|
||||||
|
call update_crc
|
||||||
|
|
||||||
|
inc d
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
ld a,e
|
||||||
|
add $10
|
||||||
|
ld e,a
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
check_crc $6A9F8D8A
|
||||||
|
|
||||||
|
jp tests_passed
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
; Tests DI, EI, and HALT (STOP proved untestable)
|
||||||
|
|
||||||
|
.include "shell.inc"
|
||||||
|
|
||||||
|
main:
|
||||||
|
wreg IE,$04
|
||||||
|
|
||||||
|
set_test 2,"EI"
|
||||||
|
ei
|
||||||
|
ld bc,0
|
||||||
|
push bc
|
||||||
|
pop bc
|
||||||
|
inc b
|
||||||
|
wreg IF,$04
|
||||||
|
interrupt_addr:
|
||||||
|
dec b
|
||||||
|
jp nz,test_failed
|
||||||
|
ld hl,sp-2
|
||||||
|
ldi a,(hl)
|
||||||
|
cp <interrupt_addr
|
||||||
|
jp nz,test_failed
|
||||||
|
ld a,(hl)
|
||||||
|
cp >interrupt_addr
|
||||||
|
jp nz,test_failed
|
||||||
|
lda IF
|
||||||
|
and $04
|
||||||
|
jp nz,test_failed
|
||||||
|
|
||||||
|
set_test 3,"DI"
|
||||||
|
di
|
||||||
|
ld bc,0
|
||||||
|
push bc
|
||||||
|
pop bc
|
||||||
|
wreg IF,$04
|
||||||
|
ld hl,sp-2
|
||||||
|
ldi a,(hl)
|
||||||
|
or (hl)
|
||||||
|
jp nz,test_failed
|
||||||
|
lda IF
|
||||||
|
and $04
|
||||||
|
jp z,test_failed
|
||||||
|
|
||||||
|
set_test 4,"Timer doesn't work"
|
||||||
|
wreg TAC,$05
|
||||||
|
wreg TIMA,0
|
||||||
|
wreg IF,0
|
||||||
|
delay 500
|
||||||
|
lda IF
|
||||||
|
delay 500
|
||||||
|
and $04
|
||||||
|
jp nz,test_failed
|
||||||
|
delay 500
|
||||||
|
lda IF
|
||||||
|
and $04
|
||||||
|
jp z,test_failed
|
||||||
|
pop af
|
||||||
|
|
||||||
|
set_test 5,"HALT"
|
||||||
|
wreg TAC,$05
|
||||||
|
wreg TIMA,0
|
||||||
|
wreg IF,0
|
||||||
|
halt ; timer interrupt will exit halt
|
||||||
|
nop ; avoids DMG bug
|
||||||
|
lda IF
|
||||||
|
and $04
|
||||||
|
jp z,test_failed
|
||||||
|
|
||||||
|
jp tests_passed
|
||||||
|
|
||||||
|
.bank 0 slot 0
|
||||||
|
.org $50
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
; Tests SP/HL instructions
|
||||||
|
|
||||||
|
;.define PRINT_CHECKSUMS 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "instr_test.s"
|
||||||
|
|
||||||
|
instrs:
|
||||||
|
.byte $33,0,0 ; INC SP
|
||||||
|
.byte $3B,0,0 ; DEC SP
|
||||||
|
.byte $39,0,0 ; ADD HL,SP
|
||||||
|
.byte $F9,0,0 ; LD SP,HL
|
||||||
|
.byte $E8,$01,0 ; ADD SP,1
|
||||||
|
.byte $E8,$FF,0 ; ADD SP,-1
|
||||||
|
.byte $F8,$01,0 ; LD HL,SP+1
|
||||||
|
.byte $F8,$FF,0 ; LD HL,SP-1
|
||||||
|
instrs_end:
|
||||||
|
|
||||||
|
test_instr:
|
||||||
|
; C = flags register
|
||||||
|
ld c,$00
|
||||||
|
call test
|
||||||
|
ld c,$F0
|
||||||
|
call test
|
||||||
|
ret
|
||||||
|
|
||||||
|
test:
|
||||||
|
; Go through each value for HL
|
||||||
|
ld hl,values
|
||||||
|
hl_loop:
|
||||||
|
ld e,(hl)
|
||||||
|
inc hl
|
||||||
|
ld d,(hl)
|
||||||
|
inc hl
|
||||||
|
push hl
|
||||||
|
|
||||||
|
; Go through each value for SP
|
||||||
|
ld hl,values
|
||||||
|
values_loop:
|
||||||
|
push bc
|
||||||
|
push de
|
||||||
|
push hl
|
||||||
|
|
||||||
|
push bc
|
||||||
|
pop af
|
||||||
|
|
||||||
|
; Switch stack
|
||||||
|
ld (temp),sp
|
||||||
|
ld a,(hl+)
|
||||||
|
ld h,(hl)
|
||||||
|
ld l,a
|
||||||
|
; call print_regs
|
||||||
|
ld sp,hl
|
||||||
|
|
||||||
|
; Set registers
|
||||||
|
ld h,d
|
||||||
|
ld l,e
|
||||||
|
ld a,$12
|
||||||
|
ld bc,$5691
|
||||||
|
ld de,$9ABC
|
||||||
|
|
||||||
|
jp instr
|
||||||
|
instr_done:
|
||||||
|
; Save new SP and switch to yet another stack
|
||||||
|
ld (temp+2),sp
|
||||||
|
ld sp,$DF70
|
||||||
|
|
||||||
|
call checksum_af_bc_de_hl
|
||||||
|
|
||||||
|
; Checksum SP
|
||||||
|
ld a,(temp+2)
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,(temp+3)
|
||||||
|
call update_crc_fast
|
||||||
|
|
||||||
|
ldsp temp
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop de
|
||||||
|
pop bc
|
||||||
|
inc hl
|
||||||
|
inc hl
|
||||||
|
ld a,l
|
||||||
|
cp <values_end
|
||||||
|
jr nz,values_loop
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
ld a,l
|
||||||
|
cp <values_end
|
||||||
|
jr nz,hl_loop
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
values:
|
||||||
|
.word $0000,$0001,$000F,$0010,$001F,$007F,$0080,$00FF
|
||||||
|
.word $0100,$0F00,$1F00,$1000,$7FFF,$8000,$FFFF
|
||||||
|
values_end:
|
||||||
|
.word $0000,$0001,$000F,$0010,$001F,$007F,$0080,$00FF
|
||||||
|
.word $0100,$0F00,$1F00,$1000,$7FFF,$8000,$FFFF
|
||||||
|
|
||||||
|
checksums:
|
||||||
|
.byte $BC,$F4,$CD,$8C,$C7,$5E,$89,$E5,$36,$65,$21,$55,$D6,$6A,$2A,$FF
|
||||||
|
.byte $EB,$34,$37,$B9,$08,$5F,$22,$13,$B6,$2A,$37,$C3,$72,$43,$5C,$4D
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
; Tests immediate instructions
|
||||||
|
|
||||||
|
;.define PRINT_CHECKSUMS 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "instr_test.s"
|
||||||
|
|
||||||
|
instrs:
|
||||||
|
.byte $36,0,0 ; LD (HL),$00
|
||||||
|
.byte $06,0,0 ; LD B,$00
|
||||||
|
.byte $0E,0,0 ; LD C,$00
|
||||||
|
.byte $16,0,0 ; LD D,$00
|
||||||
|
.byte $1E,0,0 ; LD E,$00
|
||||||
|
.byte $26,0,0 ; LD H,$00
|
||||||
|
.byte $2E,0,0 ; LD L,$00
|
||||||
|
.byte $3E,0,0 ; LD A,$00
|
||||||
|
.byte $F6,0,0 ; OR $00
|
||||||
|
.byte $FE,0,0 ; CP $00
|
||||||
|
.byte $C6,0,0 ; ADD $00
|
||||||
|
.byte $CE,0,0 ; ADC $00
|
||||||
|
.byte $D6,0,0 ; SUB $00
|
||||||
|
.byte $DE,0,0 ; SBC $00
|
||||||
|
.byte $E6,0,0 ; AND $00
|
||||||
|
.byte $EE,0,0 ; XOR $00
|
||||||
|
instrs_end:
|
||||||
|
|
||||||
|
test_instr:
|
||||||
|
ld c,$00
|
||||||
|
call test
|
||||||
|
ld c,$10
|
||||||
|
call test
|
||||||
|
ld c,$E0
|
||||||
|
call test
|
||||||
|
ld c,$F0
|
||||||
|
call test
|
||||||
|
ret
|
||||||
|
|
||||||
|
test:
|
||||||
|
; Go through each value for A
|
||||||
|
ld hl,values
|
||||||
|
a_loop:
|
||||||
|
ld b,(hl)
|
||||||
|
push hl
|
||||||
|
|
||||||
|
; Go through each value for immediate data
|
||||||
|
ld hl,values
|
||||||
|
values_loop:
|
||||||
|
push bc
|
||||||
|
push hl
|
||||||
|
|
||||||
|
; Set registers
|
||||||
|
push bc
|
||||||
|
ld a,(hl)
|
||||||
|
ld (instr+1),a
|
||||||
|
ld bc,$1234
|
||||||
|
ld de,$5678
|
||||||
|
ld hl,rp_temp
|
||||||
|
pop af
|
||||||
|
|
||||||
|
; call print_regs
|
||||||
|
jp instr
|
||||||
|
instr_done:
|
||||||
|
|
||||||
|
; Checksum registers and (hl)
|
||||||
|
call checksum_af_bc_de_hl
|
||||||
|
ld a,(rp_temp)
|
||||||
|
call update_crc_fast
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop bc
|
||||||
|
inc hl
|
||||||
|
ld a,l
|
||||||
|
cp <values_end
|
||||||
|
jr nz,values_loop
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
inc hl
|
||||||
|
ld a,l
|
||||||
|
cp <values_end
|
||||||
|
jr nz,a_loop
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
values:
|
||||||
|
.byte $00,$01,$0F,$10,$1F,$7F,$80,$F0,$FF
|
||||||
|
values_end:
|
||||||
|
|
||||||
|
checksums:
|
||||||
|
.byte $7F,$7F,$05,$B7,$85,$82,$94,$B6,$D8,$0A,$D6,$F5,$44,$8C,$37,$2A,$FB,$46,$05,$FA,$BD,$2F,$9E,$C1,$5A,$56,$2A,$DA,$D0,$EE,$14,$BA,$EA,$42,$36,$D2,$87,$28,$AB,$30,$4D,$A2,$63,$C6,$34,$4E,$55,$08,$9B,$1C,$97,$0E,$49,$F8,$73,$D4,$86,$C7,$DC,$C6,$03,$BF,$43,$21,
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
; Tests BC/DE/HL arithmetic
|
||||||
|
|
||||||
|
;.define PRINT_CHECKSUMS 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "instr_test.s"
|
||||||
|
|
||||||
|
instrs:
|
||||||
|
.byte $0B,0,0 ; DEC BC
|
||||||
|
.byte $1B,0,0 ; DEC DE
|
||||||
|
.byte $2B,0,0 ; DEC HL
|
||||||
|
.byte $03,0,0 ; INC BC
|
||||||
|
.byte $13,0,0 ; INC DE
|
||||||
|
.byte $23,0,0 ; INC HL
|
||||||
|
.byte $09,0,0 ; ADD HL,BC
|
||||||
|
.byte $19,0,0 ; ADD HL,DE
|
||||||
|
.byte $29,0,0 ; ADD HL,HL
|
||||||
|
instrs_end:
|
||||||
|
|
||||||
|
test_instr:
|
||||||
|
ld c,$00
|
||||||
|
call test
|
||||||
|
ld c,$10
|
||||||
|
call test
|
||||||
|
ld c,$E0
|
||||||
|
call test
|
||||||
|
ld c,$F0
|
||||||
|
call test
|
||||||
|
ret
|
||||||
|
|
||||||
|
test:
|
||||||
|
; Go through each value for HL
|
||||||
|
ld hl,values
|
||||||
|
hl_loop:
|
||||||
|
ld e,(hl)
|
||||||
|
inc hl
|
||||||
|
ld d,(hl)
|
||||||
|
inc hl
|
||||||
|
push hl
|
||||||
|
|
||||||
|
; Go through each value for BC, DE, A
|
||||||
|
ld hl,values
|
||||||
|
values_loop:
|
||||||
|
push bc
|
||||||
|
push de
|
||||||
|
push hl
|
||||||
|
|
||||||
|
push de
|
||||||
|
push bc
|
||||||
|
|
||||||
|
; BC
|
||||||
|
ld c,(hl)
|
||||||
|
inc hl
|
||||||
|
ld b,(hl)
|
||||||
|
inc hl
|
||||||
|
|
||||||
|
; DE
|
||||||
|
ld e,(hl)
|
||||||
|
inc hl
|
||||||
|
ld d,(hl)
|
||||||
|
inc hl
|
||||||
|
|
||||||
|
; HL, AF
|
||||||
|
pop af
|
||||||
|
ld a,(hl)
|
||||||
|
pop hl
|
||||||
|
|
||||||
|
; call print_regs
|
||||||
|
jp instr
|
||||||
|
instr_done:
|
||||||
|
|
||||||
|
; Checksum registers
|
||||||
|
call checksum_af_bc_de_hl
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop de
|
||||||
|
pop bc
|
||||||
|
inc hl
|
||||||
|
inc hl
|
||||||
|
ld a,l
|
||||||
|
cp <values_end
|
||||||
|
jr nz,values_loop
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
ld a,l
|
||||||
|
cp <values_end
|
||||||
|
jr nz,hl_loop
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
values:
|
||||||
|
.word $0000,$0001,$000F,$0010,$001F,$007F,$0080,$00FF
|
||||||
|
.word $0100,$0F00,$1F00,$1000,$7FFF,$8000,$FFFF
|
||||||
|
values_end:
|
||||||
|
.word $0000,$0001,$000F,$0010,$001F,$007F,$0080,$00FF
|
||||||
|
.word $0100,$0F00,$1F00,$1000,$7FFF,$8000,$FFFF
|
||||||
|
|
||||||
|
checksums:
|
||||||
|
.byte $C0,$A1,$36,$A3,$BE,$15,$B8,$2B,$9F,$93,$C6,$C2,$86,$C0,$07,$81,$0F,$75,$35,$38,$6B,$C7,$0A,$1B,$06,$68,$4B,$42,$64,$B4,$8C,$18,$FB,$6C,$31,$94,
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
; Tests LD r,r ($40-$7F)
|
||||||
|
|
||||||
|
;.define PRINT_CHECKSUMS 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "instr_test.s"
|
||||||
|
|
||||||
|
instrs:
|
||||||
|
.byte $40,0,0 ; LD B,B
|
||||||
|
.byte $41,0,0 ; LD B,C
|
||||||
|
.byte $42,0,0 ; LD B,D
|
||||||
|
.byte $43,0,0 ; LD B,E
|
||||||
|
.byte $44,0,0 ; LD B,H
|
||||||
|
.byte $45,0,0 ; LD B,L
|
||||||
|
.byte $46,0,0 ; LD B,(HL)
|
||||||
|
.byte $47,0,0 ; LD B,A
|
||||||
|
|
||||||
|
.byte $48,0,0 ; LD C,B
|
||||||
|
.byte $49,0,0 ; LD C,C
|
||||||
|
.byte $4A,0,0 ; LD C,D
|
||||||
|
.byte $4B,0,0 ; LD C,E
|
||||||
|
.byte $4C,0,0 ; LD C,H
|
||||||
|
.byte $4D,0,0 ; LD C,L
|
||||||
|
.byte $4E,0,0 ; LD C,(HL)
|
||||||
|
.byte $4F,0,0 ; LD C,A
|
||||||
|
|
||||||
|
.byte $50,0,0 ; LD D,B
|
||||||
|
.byte $51,0,0 ; LD D,C
|
||||||
|
.byte $52,0,0 ; LD D,D
|
||||||
|
.byte $53,0,0 ; LD D,E
|
||||||
|
.byte $54,0,0 ; LD D,H
|
||||||
|
.byte $55,0,0 ; LD D,L
|
||||||
|
.byte $56,0,0 ; LD D,(HL)
|
||||||
|
.byte $57,0,0 ; LD D,A
|
||||||
|
|
||||||
|
.byte $58,0,0 ; LD E,B
|
||||||
|
.byte $59,0,0 ; LD E,C
|
||||||
|
.byte $5A,0,0 ; LD E,D
|
||||||
|
.byte $5B,0,0 ; LD E,E
|
||||||
|
.byte $5C,0,0 ; LD E,H
|
||||||
|
.byte $5D,0,0 ; LD E,L
|
||||||
|
.byte $5E,0,0 ; LD E,(HL)
|
||||||
|
.byte $5F,0,0 ; LD E,A
|
||||||
|
|
||||||
|
.byte $60,0,0 ; LD H,B
|
||||||
|
.byte $61,0,0 ; LD H,C
|
||||||
|
.byte $62,0,0 ; LD H,D
|
||||||
|
.byte $63,0,0 ; LD H,E
|
||||||
|
.byte $64,0,0 ; LD H,H
|
||||||
|
.byte $65,0,0 ; LD H,L
|
||||||
|
.byte $66,0,0 ; LD H,(HL)
|
||||||
|
.byte $67,0,0 ; LD H,A
|
||||||
|
|
||||||
|
.byte $68,0,0 ; LD L,B
|
||||||
|
.byte $69,0,0 ; LD L,C
|
||||||
|
.byte $6A,0,0 ; LD L,D
|
||||||
|
.byte $6B,0,0 ; LD L,E
|
||||||
|
.byte $6C,0,0 ; LD L,H
|
||||||
|
.byte $6D,0,0 ; LD L,L
|
||||||
|
.byte $6E,0,0 ; LD L,(HL)
|
||||||
|
.byte $6F,0,0 ; LD L,A
|
||||||
|
|
||||||
|
.byte $70,0,0 ; LD (HL),B
|
||||||
|
.byte $71,0,0 ; LD (HL),C
|
||||||
|
.byte $72,0,0 ; LD (HL),D
|
||||||
|
.byte $73,0,0 ; LD (HL),E
|
||||||
|
.byte $74,0,0 ; LD (HL),H
|
||||||
|
.byte $75,0,0 ; LD (HL),L
|
||||||
|
.byte $77,0,0 ; LD (HL),A
|
||||||
|
|
||||||
|
.byte $78,0,0 ; LD A,B
|
||||||
|
.byte $79,0,0 ; LD A,C
|
||||||
|
.byte $7A,0,0 ; LD A,D
|
||||||
|
.byte $7B,0,0 ; LD A,E
|
||||||
|
.byte $7C,0,0 ; LD A,H
|
||||||
|
.byte $7D,0,0 ; LD A,L
|
||||||
|
.byte $7E,0,0 ; LD A,(HL)
|
||||||
|
.byte $7F,0,0 ; LD A,A
|
||||||
|
instrs_end:
|
||||||
|
|
||||||
|
test_instr:
|
||||||
|
ld c,$00
|
||||||
|
call test
|
||||||
|
ld c,$10
|
||||||
|
call test
|
||||||
|
ld c,$E0
|
||||||
|
call test
|
||||||
|
ld c,$F0
|
||||||
|
call test
|
||||||
|
ret
|
||||||
|
|
||||||
|
test:
|
||||||
|
; Put different value in each register and (hl_temp)
|
||||||
|
ld b,$BC
|
||||||
|
push bc
|
||||||
|
ld a,$DE
|
||||||
|
ld (rp_temp),a
|
||||||
|
ld a,$12
|
||||||
|
ld bc,$3456
|
||||||
|
ld de,$789A
|
||||||
|
ld hl,rp_temp ; (HL) points to RAM
|
||||||
|
pop af
|
||||||
|
|
||||||
|
; call print_regs
|
||||||
|
jp instr
|
||||||
|
instr_done:
|
||||||
|
|
||||||
|
; Checksum registers and (HL)
|
||||||
|
call checksum_af_bc_de_hl
|
||||||
|
ld a,(rp_temp)
|
||||||
|
call update_crc_fast
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
checksums:
|
||||||
|
.byte $40,$3A,$AF,$06,$B6,$CB,$B2,$AB,$6F,$EF,$71,$9B,$75,$E3,$6C,$B9,$34,$FB,$26,$B7,$5A,$B9,$2F,$CE,$34,$FB,$26,$B7,$C2,$0A,$3B,$1A,$2A,$8A,$D6,$7C,$40,$3A,$AF,$06,$AF,$0A,$74,$70,$19,$A9,$6E,$6F,$11,$DA,$FE,$FE,$18,$10,$04,$2B,$11,$DA,$FE,$FE,$7B,$6A,$87,$84,$8B,$87,$34,$12,$00,$45,$DE,$01,$40,$3A,$AF,$06,$93,$E2,$8F,$C6,$DD,$7D,$90,$32,$FF,$90,$1B,$A8,$DD,$7D,$90,$32,$56,$BF,$7A,$21,$23,$C0,$FA,$06,$3B,$1D,$A0,$80,$3F,$44,$1B,$9C,$40,$3A,$AF,$06,$56,$25,$85,$CD,$D7,$B1,$DB,$F9,$56,$25,$85,$CD,$4E,$F8,$DF,$4B,$F0,$C3,$F9,$18,$20,$0F,$F6,$91,$71,$69,$CE,$46,$F0,$A0,$03,$4D,$40,$3A,$AF,$06,$29,$47,$E2,$36,$40,$3A,$AF,$06,$90,$F6,$A0,$8F,$3D,$62,$26,$A9,$A4,$52,$C1,$75,$45,$ED,$75,$40,$8A,$4D,$63,$56,$AF,$BA,$2D,$FE,$40,$3A,$AF,$06,$AF,$BA,$2D,$FE,$36,$8A,$CA,$22,$34,$8D,$C2,$65,$1A,$DB,$FF,$54,$32,$C0,$E8,$55,$ED,$4A,$87,$2F,$40,$3A,$AF,$06,$9D,$BC,$81,$E6,$6E,$6C,$92,$37,$B1,$EC,$C3,$29,$1D,$C5,$9F,$A1,$59,$6F,$66,$CD,$B4,$FB,$FD,$74,$EC,$13,$F3,$8E,$70,$0C,$5F,$ED,$EC,$13,$F3,$8E,$40,$3A,$AF,$06,
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
; Tests branch instructions
|
||||||
|
|
||||||
|
;.define PRINT_CHECKSUMS 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "instr_test.s"
|
||||||
|
|
||||||
|
instrs:
|
||||||
|
; JR cond,skip
|
||||||
|
; INC A
|
||||||
|
; skip:
|
||||||
|
.byte $18,$01,$3C ; JR *+3
|
||||||
|
.byte $20,$01,$3C ; JR NZ,*+3
|
||||||
|
.byte $28,$01,$3C ; JR Z,*+3
|
||||||
|
.byte $30,$01,$3C ; JR NC,*+3
|
||||||
|
.byte $38,$01,$3C ; JR C,*+3
|
||||||
|
|
||||||
|
.byte $C2,<taken,>taken ; JP NZ,taken
|
||||||
|
.byte $C3,<taken,>taken ; JP taken
|
||||||
|
.byte $CA,<taken,>taken ; JP Z,taken
|
||||||
|
.byte $D2,<taken,>taken ; JP NC,taken
|
||||||
|
.byte $DA,<taken,>taken ; JP C,taken
|
||||||
|
|
||||||
|
.byte $C4,<taken,>taken ; CALL NZ,taken
|
||||||
|
.byte $CC,<taken,>taken ; CALL Z,taken
|
||||||
|
.byte $CD,<taken,>taken ; CALL taken
|
||||||
|
.byte $D4,<taken,>taken ; CALL NC,taken
|
||||||
|
.byte $DC,<taken,>taken ; CALL C,taken
|
||||||
|
|
||||||
|
; RET cond
|
||||||
|
; INC A
|
||||||
|
.byte $C0,$3C,0 ; RET NZ
|
||||||
|
.byte $C8,$3C,0 ; RET Z
|
||||||
|
.byte $C9,$3C,0 ; RET
|
||||||
|
.byte $D0,$3C,0 ; RET NC
|
||||||
|
.byte $D8,$3C,0 ; RET C
|
||||||
|
.byte $D9,$3C,0 ; RETI
|
||||||
|
|
||||||
|
; RST
|
||||||
|
; can only easily test this one on devcart
|
||||||
|
.byte $C7,0,0 ; RST $00
|
||||||
|
.ifndef BUILD_DEVCART
|
||||||
|
.byte $CF,0,0 ; RST $08
|
||||||
|
.byte $D7,0,0 ; RST $10
|
||||||
|
.byte $DF,0,0 ; RST $18
|
||||||
|
.byte $E7,0,0 ; RST $20
|
||||||
|
.byte $EF,0,0 ; RST $28
|
||||||
|
.byte $F7,0,0 ; RST $30
|
||||||
|
.byte $FF,0,0 ; RST $38
|
||||||
|
.endif
|
||||||
|
|
||||||
|
instrs_end:
|
||||||
|
|
||||||
|
test_instr:
|
||||||
|
wreg IE,0 ; disable interrupts, since RETI does EI
|
||||||
|
|
||||||
|
; Go through all 16 combinations of flags
|
||||||
|
ld bc,$1200
|
||||||
|
-
|
||||||
|
; Fill 4 bytes of new stack
|
||||||
|
ld a,$12
|
||||||
|
ld ($DF80-2),a
|
||||||
|
ld a,$34
|
||||||
|
ld ($DF80-3),a
|
||||||
|
ld a,$56
|
||||||
|
ld ($DF80-4),a
|
||||||
|
ld a,$78
|
||||||
|
ld ($DF80-5),a
|
||||||
|
|
||||||
|
; Set AF
|
||||||
|
push bc
|
||||||
|
pop af
|
||||||
|
|
||||||
|
; Switch to new stack
|
||||||
|
ld (temp),sp
|
||||||
|
ld sp,$DF80
|
||||||
|
|
||||||
|
; Set return address
|
||||||
|
ld de,instr+3
|
||||||
|
push de
|
||||||
|
|
||||||
|
jp instr
|
||||||
|
instr_done:
|
||||||
|
inc a
|
||||||
|
taken:
|
||||||
|
di ; RETI enables interrupts
|
||||||
|
|
||||||
|
; Save new SP and switch to yet another stack
|
||||||
|
ld (temp+2),sp
|
||||||
|
ld sp,$DF70
|
||||||
|
|
||||||
|
; Checksum A and SP
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,(temp+2)
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,(temp+3)
|
||||||
|
call update_crc_fast
|
||||||
|
|
||||||
|
; Checksum 4 bytes of stack
|
||||||
|
ld a,($DF80-2)
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,($DF80-3)
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,($DF80-4)
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,($DF80-5)
|
||||||
|
call update_crc_fast
|
||||||
|
|
||||||
|
ldsp temp
|
||||||
|
|
||||||
|
ld a,c
|
||||||
|
add $10
|
||||||
|
ld c,a
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
checksums:
|
||||||
|
.byte $EC,$A4,$94,$79,$C4,$00,$96,$2C,$C4,$64,$90,$33,$77,$C7,$0A,$D4
|
||||||
|
.byte $77,$A3,$0C,$CB,$79,$E7,$7E,$AE,$DA,$DC,$03,$F7,$4F,$9F,$E9,$20
|
||||||
|
.byte $72,$12,$DA,$01,$44,$6A,$4D,$8F,$D1,$79,$30,$4C,$AA,$37,$F2,$6A
|
||||||
|
.byte $97,$EA,$56,$5F,$32,$28,$C7,$D1,$49,$66,$05,$F7,$80,$0F,$BA,$8E
|
||||||
|
.byte $41,$E2,$A4,$9A,$2D,$2D,$8C,$72,$A5,$13,$76,$A8,$64,$FE,$68,$BC
|
||||||
|
.byte $2D,$2D,$8C,$72,$50,$96,$24,$27,$50,$96,$24,$27,$50,$96,$24,$27
|
||||||
|
.byte $50,$96,$24,$27,$50,$96,$24,$27,$50,$96,$24,$27,$50,$96,$24,$27
|
||||||
|
.byte $50,$96,$24,$27
|
||||||
|
|
||||||
|
.include "multi_custom.s"
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
; Tests miscellaneous instructions
|
||||||
|
|
||||||
|
;.define PRINT_CHECKSUMS 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "instr_test.s"
|
||||||
|
|
||||||
|
instrs:
|
||||||
|
.byte $F0,$91,0 ; LDH A,($91)
|
||||||
|
.byte $E0,$91,0 ; LDH ($91),A
|
||||||
|
.byte $F2,$00,0 ; LDH A,(C)
|
||||||
|
.byte $E2,$00,0 ; LDH (C),A
|
||||||
|
.byte $FA,$91,$FF ; LD A,($FF91)
|
||||||
|
.byte $EA,$91,$FF ; LD ($FF91),A
|
||||||
|
.byte $08,$91,$FF ; LD ($FF91),SP
|
||||||
|
.byte $01,$23,$01 ; LD BC,$0123
|
||||||
|
.byte $11,$23,$01 ; LD DE,$0123
|
||||||
|
.byte $21,$23,$01 ; LD HL,$0123
|
||||||
|
.byte $31,$23,$01 ; LD SP,$0123
|
||||||
|
.byte $F5,0,0 ; PUSH AF
|
||||||
|
.byte $C5,0,0 ; PUSH BC
|
||||||
|
.byte $D5,0,0 ; PUSH DE
|
||||||
|
.byte $E5,0,0 ; PUSH HL
|
||||||
|
.byte $F1,0,0 ; POP AF
|
||||||
|
.byte $C1,0,0 ; POP BC
|
||||||
|
.byte $D1,0,0 ; POP DE
|
||||||
|
.byte $E1,0,0 ; POP HL
|
||||||
|
instrs_end:
|
||||||
|
|
||||||
|
test_instr:
|
||||||
|
; C = flags register
|
||||||
|
ld c,$00
|
||||||
|
call test
|
||||||
|
ld c,$10
|
||||||
|
call test
|
||||||
|
ld c,$E0
|
||||||
|
call test
|
||||||
|
ld c,$F0
|
||||||
|
call test
|
||||||
|
ret
|
||||||
|
|
||||||
|
test:
|
||||||
|
; Fill RAM
|
||||||
|
ld a,$FE
|
||||||
|
ld ($FF90),a
|
||||||
|
ld a,$DC
|
||||||
|
ld ($FF91),a
|
||||||
|
ld a,$BA
|
||||||
|
ld ($FF92),a
|
||||||
|
|
||||||
|
; Fill stack
|
||||||
|
ld a,$13
|
||||||
|
ld ($DF80),a
|
||||||
|
ld a,$57
|
||||||
|
ld ($DF80-1),a
|
||||||
|
ld a,$9B
|
||||||
|
ld ($DF80-2),a
|
||||||
|
ld a,$DF
|
||||||
|
ld ($DF80-3),a
|
||||||
|
|
||||||
|
; Set registers
|
||||||
|
ld b,$12
|
||||||
|
push bc
|
||||||
|
ld bc,$5691
|
||||||
|
ld de,$9ABC
|
||||||
|
ld hl,$DEF0
|
||||||
|
pop af
|
||||||
|
|
||||||
|
; Switch stack
|
||||||
|
ld (temp),sp
|
||||||
|
ld sp,$DF80-2
|
||||||
|
|
||||||
|
jp instr
|
||||||
|
instr_done:
|
||||||
|
; Save new SP and switch to another stack
|
||||||
|
ld (temp+2),sp
|
||||||
|
ld sp,$DF70
|
||||||
|
|
||||||
|
call checksum_af_bc_de_hl
|
||||||
|
|
||||||
|
; Checksum SP
|
||||||
|
ld a,(temp+2)
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,(temp+3)
|
||||||
|
call update_crc_fast
|
||||||
|
|
||||||
|
; Checksum RAM
|
||||||
|
ld a,($FF90)
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,($FF91)
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,($FF92)
|
||||||
|
call update_crc_fast
|
||||||
|
|
||||||
|
; Checksum stack
|
||||||
|
ld a,($DF80)
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,($DF80-1)
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,($DF80-2)
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,($DF80-3)
|
||||||
|
call update_crc_fast
|
||||||
|
|
||||||
|
; Restore SP
|
||||||
|
ldsp temp
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
checksums:
|
||||||
|
.byte $4D,$FF,$15,$97,$6D,$A7,$35,$65,$4D,$FF,$15,$97,$6D,$A7,$35,$65,$4D,$FF,$15,$97,$6D,$A7,$35,$65,$AD,$FA,$5E,$41,$D0,$78,$79,$C1,$AF,$66,$99,$34,$0D,$E1,$97,$99,$6F,$D0,$6F,$5D,$C3,$1F,$A3,$8A,$C2,$F1,$9C,$F3,$C1,$C3,$DC,$78,$C0,$2D,$E3,$01,$8F,$C4,$0F,$44,$95,$22,$6A,$39,$61,$C5,$AB,$55,$FB,$DF,$2C,$52,
|
||||||
|
|
@ -0,0 +1,269 @@
|
||||||
|
; Tests most register instructions.
|
||||||
|
; Takes 10 seconds.
|
||||||
|
|
||||||
|
;.define PRINT_CHECKSUMS 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "instr_test.s"
|
||||||
|
|
||||||
|
instrs:
|
||||||
|
.byte $00,0,0 ; NOP
|
||||||
|
.byte $2F,0,0 ; CPL
|
||||||
|
.byte $37,0,0 ; SCF
|
||||||
|
.byte $3F,0,0 ; CCF
|
||||||
|
|
||||||
|
.byte $B0,0,0 ; OR B
|
||||||
|
.byte $B1,0,0 ; OR C
|
||||||
|
.byte $B2,0,0 ; OR D
|
||||||
|
.byte $B3,0,0 ; OR E
|
||||||
|
.byte $B4,0,0 ; OR H
|
||||||
|
.byte $B5,0,0 ; OR L
|
||||||
|
.byte $B7,0,0 ; OR A
|
||||||
|
|
||||||
|
.byte $B8,0,0 ; CP B
|
||||||
|
.byte $B9,0,0 ; CP C
|
||||||
|
.byte $BA,0,0 ; CP D
|
||||||
|
.byte $BB,0,0 ; CP E
|
||||||
|
.byte $BC,0,0 ; CP H
|
||||||
|
.byte $BD,0,0 ; CP L
|
||||||
|
.byte $BF,0,0 ; CP A
|
||||||
|
|
||||||
|
.byte $80,0,0 ; ADD B
|
||||||
|
.byte $81,0,0 ; ADD C
|
||||||
|
.byte $82,0,0 ; ADD D
|
||||||
|
.byte $83,0,0 ; ADD E
|
||||||
|
.byte $84,0,0 ; ADD H
|
||||||
|
.byte $85,0,0 ; ADD L
|
||||||
|
.byte $87,0,0 ; ADD A
|
||||||
|
|
||||||
|
.byte $88,0,0 ; ADC B
|
||||||
|
.byte $89,0,0 ; ADC C
|
||||||
|
.byte $8A,0,0 ; ADC D
|
||||||
|
.byte $8B,0,0 ; ADC E
|
||||||
|
.byte $8C,0,0 ; ADC H
|
||||||
|
.byte $8D,0,0 ; ADC L
|
||||||
|
.byte $8F,0,0 ; ADC A
|
||||||
|
|
||||||
|
.byte $90,0,0 ; SUB B
|
||||||
|
.byte $91,0,0 ; SUB C
|
||||||
|
.byte $92,0,0 ; SUB D
|
||||||
|
.byte $93,0,0 ; SUB E
|
||||||
|
.byte $94,0,0 ; SUB H
|
||||||
|
.byte $95,0,0 ; SUB L
|
||||||
|
.byte $97,0,0 ; SUB A
|
||||||
|
|
||||||
|
.byte $98,0,0 ; SBC B
|
||||||
|
.byte $99,0,0 ; SBC C
|
||||||
|
.byte $9A,0,0 ; SBC D
|
||||||
|
.byte $9B,0,0 ; SBC E
|
||||||
|
.byte $9C,0,0 ; SBC H
|
||||||
|
.byte $9D,0,0 ; SBC L
|
||||||
|
.byte $9F,0,0 ; SBC A
|
||||||
|
|
||||||
|
.byte $A0,0,0 ; AND B
|
||||||
|
.byte $A1,0,0 ; AND C
|
||||||
|
.byte $A2,0,0 ; AND D
|
||||||
|
.byte $A3,0,0 ; AND E
|
||||||
|
.byte $A4,0,0 ; AND H
|
||||||
|
.byte $A5,0,0 ; AND L
|
||||||
|
.byte $A7,0,0 ; AND A
|
||||||
|
|
||||||
|
.byte $A8,0,0 ; XOR B
|
||||||
|
.byte $A9,0,0 ; XOR C
|
||||||
|
.byte $AA,0,0 ; XOR D
|
||||||
|
.byte $AB,0,0 ; XOR E
|
||||||
|
.byte $AC,0,0 ; XOR H
|
||||||
|
.byte $AD,0,0 ; XOR L
|
||||||
|
.byte $AF,0,0 ; XOR A
|
||||||
|
|
||||||
|
.byte $05,0,0 ; DEC B
|
||||||
|
.byte $0D,0,0 ; DEC C
|
||||||
|
.byte $15,0,0 ; DEC D
|
||||||
|
.byte $1D,0,0 ; DEC E
|
||||||
|
.byte $25,0,0 ; DEC H
|
||||||
|
.byte $2D,0,0 ; DEC L
|
||||||
|
.byte $3D,0,0 ; DEC A
|
||||||
|
|
||||||
|
.byte $04,0,0 ; INC B
|
||||||
|
.byte $0C,0,0 ; INC C
|
||||||
|
.byte $14,0,0 ; INC D
|
||||||
|
.byte $1C,0,0 ; INC E
|
||||||
|
.byte $24,0,0 ; INC H
|
||||||
|
.byte $2C,0,0 ; INC L
|
||||||
|
.byte $3C,0,0 ; INC A
|
||||||
|
|
||||||
|
.byte $07,0,0 ; RLCA
|
||||||
|
.byte $17,0,0 ; RLA
|
||||||
|
.byte $0F,0,0 ; RRCA
|
||||||
|
.byte $1F,0,0 ; RRA
|
||||||
|
|
||||||
|
.byte $CB,$00,0 ; RLC B
|
||||||
|
.byte $CB,$01,0 ; RLC C
|
||||||
|
.byte $CB,$02,0 ; RLC D
|
||||||
|
.byte $CB,$03,0 ; RLC E
|
||||||
|
.byte $CB,$04,0 ; RLC H
|
||||||
|
.byte $CB,$05,0 ; RLC L
|
||||||
|
.byte $CB,$07,0 ; RLC A
|
||||||
|
|
||||||
|
.byte $CB,$08,0 ; RRC B
|
||||||
|
.byte $CB,$09,0 ; RRC C
|
||||||
|
.byte $CB,$0A,0 ; RRC D
|
||||||
|
.byte $CB,$0B,0 ; RRC E
|
||||||
|
.byte $CB,$0C,0 ; RRC H
|
||||||
|
.byte $CB,$0D,0 ; RRC L
|
||||||
|
.byte $CB,$0F,0 ; RRC A
|
||||||
|
|
||||||
|
.byte $CB,$10,0 ; RL B
|
||||||
|
.byte $CB,$11,0 ; RL C
|
||||||
|
.byte $CB,$12,0 ; RL D
|
||||||
|
.byte $CB,$13,0 ; RL E
|
||||||
|
.byte $CB,$14,0 ; RL H
|
||||||
|
.byte $CB,$15,0 ; RL L
|
||||||
|
.byte $CB,$17,0 ; RL A
|
||||||
|
|
||||||
|
.byte $CB,$18,0 ; RR B
|
||||||
|
.byte $CB,$19,0 ; RR C
|
||||||
|
.byte $CB,$1A,0 ; RR D
|
||||||
|
.byte $CB,$1B,0 ; RR E
|
||||||
|
.byte $CB,$1C,0 ; RR H
|
||||||
|
.byte $CB,$1D,0 ; RR L
|
||||||
|
.byte $CB,$1F,0 ; RR A
|
||||||
|
|
||||||
|
.byte $CB,$20,0 ; SLA B
|
||||||
|
.byte $CB,$21,0 ; SLA C
|
||||||
|
.byte $CB,$22,0 ; SLA D
|
||||||
|
.byte $CB,$23,0 ; SLA E
|
||||||
|
.byte $CB,$24,0 ; SLA H
|
||||||
|
.byte $CB,$25,0 ; SLA L
|
||||||
|
.byte $CB,$27,0 ; SLA A
|
||||||
|
|
||||||
|
.byte $CB,$28,0 ; SRA B
|
||||||
|
.byte $CB,$29,0 ; SRA C
|
||||||
|
.byte $CB,$2A,0 ; SRA D
|
||||||
|
.byte $CB,$2B,0 ; SRA E
|
||||||
|
.byte $CB,$2C,0 ; SRA H
|
||||||
|
.byte $CB,$2D,0 ; SRA L
|
||||||
|
.byte $CB,$2F,0 ; SRA A
|
||||||
|
|
||||||
|
.byte $CB,$30,0 ; SWAP B
|
||||||
|
.byte $CB,$31,0 ; SWAP C
|
||||||
|
.byte $CB,$32,0 ; SWAP D
|
||||||
|
.byte $CB,$33,0 ; SWAP E
|
||||||
|
.byte $CB,$34,0 ; SWAP H
|
||||||
|
.byte $CB,$35,0 ; SWAP L
|
||||||
|
.byte $CB,$37,0 ; SWAP A
|
||||||
|
|
||||||
|
.byte $CB,$38,0 ; SRL B
|
||||||
|
.byte $CB,$39,0 ; SRL C
|
||||||
|
.byte $CB,$3A,0 ; SRL D
|
||||||
|
.byte $CB,$3B,0 ; SRL E
|
||||||
|
.byte $CB,$3C,0 ; SRL H
|
||||||
|
.byte $CB,$3D,0 ; SRL L
|
||||||
|
.byte $CB,$3F,0 ; SRL A
|
||||||
|
instrs_end:
|
||||||
|
|
||||||
|
test_instr:
|
||||||
|
ld c,$00
|
||||||
|
call test
|
||||||
|
ld c,$F0
|
||||||
|
call test
|
||||||
|
ret
|
||||||
|
|
||||||
|
test:
|
||||||
|
; Go through each value for A
|
||||||
|
ld hl,values
|
||||||
|
a_loop:
|
||||||
|
ld b,(hl)
|
||||||
|
push hl
|
||||||
|
|
||||||
|
; Go through each value for other registers
|
||||||
|
ld hl,values
|
||||||
|
values_loop:
|
||||||
|
push bc
|
||||||
|
push hl
|
||||||
|
|
||||||
|
push bc
|
||||||
|
|
||||||
|
; BC
|
||||||
|
ld a,(hl+)
|
||||||
|
ld b,a
|
||||||
|
ld a,(hl+)
|
||||||
|
ld c,a
|
||||||
|
|
||||||
|
; HL
|
||||||
|
ld a,(hl+)
|
||||||
|
ld d,a
|
||||||
|
ld a,(hl+)
|
||||||
|
ld e,a
|
||||||
|
push de
|
||||||
|
|
||||||
|
; DE
|
||||||
|
ld a,(hl+)
|
||||||
|
ld d,a
|
||||||
|
ld a,(hl+)
|
||||||
|
ld e,a
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop af
|
||||||
|
|
||||||
|
; call print_regs
|
||||||
|
jp instr
|
||||||
|
instr_done:
|
||||||
|
|
||||||
|
; Checksum registers
|
||||||
|
call checksum_af_bc_de_hl
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop bc
|
||||||
|
inc hl
|
||||||
|
ld a,l
|
||||||
|
cp <values_end
|
||||||
|
jr nz,values_loop
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
inc hl
|
||||||
|
ld a,l
|
||||||
|
cp <values_end
|
||||||
|
jr nz,a_loop
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
values:
|
||||||
|
.byte $00,$01,$0F,$10,$1F,$7F,$80,$F0,$FF
|
||||||
|
values_end:
|
||||||
|
.byte $00,$01,$0F,$10,$1F,$7F,$80,$F0,$FF
|
||||||
|
|
||||||
|
checksums:
|
||||||
|
.byte $7C,$55,$BD,$05,$BA,$C7,$AC,$D1,$74,$6D,$82,$4A,$0F,$06,$2A,$C5
|
||||||
|
.byte $FA,$97,$9B,$9D,$C3,$32,$A0,$78,$00,$C1,$9F,$69,$C0,$D1,$C2,$A1
|
||||||
|
.byte $55,$0D,$3F,$C8,$09,$7D,$97,$92,$CE,$66,$30,$56,$95,$F3,$01,$A1
|
||||||
|
.byte $5B,$97,$54,$4C,$56,$FC,$A0,$89,$42,$F8,$7B,$2A,$E6,$7C,$03,$40
|
||||||
|
.byte $45,$60,$C5,$A8,$B7,$BF,$B0,$EF,$A0,$7A,$1B,$4F,$FB,$22,$B4,$33
|
||||||
|
.byte $06,$3D,$B5,$C7,$3C,$A4,$D5,$23,$C1,$BE,$75,$8B,$E0,$9B,$98,$BB
|
||||||
|
.byte $0E,$75,$D9,$E6,$82,$A7,$E2,$66,$CD,$78,$4F,$E8,$8E,$D4,$2D,$3E
|
||||||
|
.byte $88,$5C,$58,$C7,$F9,$20,$5F,$B9,$A8,$E4,$CA,$5E,$C8,$DB,$88,$94
|
||||||
|
.byte $A3,$0D,$87,$60,$8B,$BA,$2B,$27,$41,$88,$83,$B1,$0A,$41,$9E,$D6
|
||||||
|
.byte $98,$8D,$19,$B7,$13,$C6,$D5,$BF,$83,$CE,$74,$9F,$00,$34,$07,$5E
|
||||||
|
.byte $F0,$E1,$1A,$68,$8F,$BA,$85,$A7,$A0,$46,$06,$A5,$75,$F9,$83,$48
|
||||||
|
.byte $12,$EF,$1B,$03,$C8,$FB,$79,$EA,$9B,$00,$6C,$A9,$0D,$5E,$CB,$57
|
||||||
|
.byte $41,$1B,$4B,$0C,$B2,$08,$D8,$E3,$43,$07,$E1,$93,$34,$73,$23,$C9
|
||||||
|
.byte $18,$2F,$38,$F9,$D1,$3B,$AB,$5A,$BF,$C6,$F8,$03,$50,$0C,$A4,$32
|
||||||
|
.byte $6B,$06,$7E,$FE,$ED,$8B,$D4,$15,$29,$46,$6D,$24,$6E,$5B,$15,$1A
|
||||||
|
.byte $32,$AE,$87,$B0,$DC,$20,$AC,$4B,$2B,$63,$60,$C7,$C1,$92,$75,$AA
|
||||||
|
.byte $6F,$CA,$17,$53,$5A,$C5,$78,$EA,$61,$01,$10,$83,$DD,$08,$D8,$78
|
||||||
|
.byte $CA,$0B,$F5,$1F,$92,$55,$08,$01,$7F,$EA,$CD,$9B,$2A,$AA,$73,$17
|
||||||
|
.byte $E0,$9F,$D0,$BA,$E7,$73,$72,$3D,$B7,$95,$2F,$3B,$A7,$78,$50,$36
|
||||||
|
.byte $81,$04,$5B,$9E,$9A,$DE,$A4,$DD,$21,$B2,$9B,$36,$9F,$D7,$C8,$32
|
||||||
|
.byte $48,$0E,$FC,$E5,$55,$C3,$53,$75,$A4,$ED,$A9,$E0,$9E,$78,$A7,$1D
|
||||||
|
.byte $B8,$F4,$7C,$D6,$90,$2A,$03,$87,$81,$D8,$D5,$90,$63,$02,$C4,$52
|
||||||
|
.byte $C2,$BE,$85,$B3,$32,$9A,$9E,$2D,$E3,$FB,$22,$47,$8E,$65,$08,$73
|
||||||
|
.byte $72,$5A,$73,$95,$ED,$EC,$59,$9D,$C8,$67,$68,$F1,$4B,$ED,$41,$D5
|
||||||
|
.byte $68,$39,$75,$F3,$FC,$09,$EF,$0D,$20,$2B,$43,$A3,$69,$AA,$89,$4F
|
||||||
|
.byte $84,$87,$7B,$58,$42,$0A,$56,$EF,$1B,$0E,$19,$CA,$6F,$1B,$F9,$17
|
||||||
|
.byte $EA,$B6,$4C,$B2,$1A,$C4,$C0,$B1,$E2,$B2,$45,$4E,$91,$0A,$8D,$AE
|
||||||
|
.byte $17,$31,$55,$A3,$1B,$69,$72,$D8,$03,$E9,$55,$8D,$87,$27,$36,$63
|
||||||
|
.byte $E6,$85,$12,$D1,$F2,$32,$97,$4D,$B5,$FA,$08,$A9,$97,$2A,$5A,$C2
|
||||||
|
.byte $FD,$2D,$A4,$27,$57,$7C,$EC,$BD,$CC,$67,$19,$21,$46,$D4,$CD,$D6
|
||||||
|
.byte $CB,$55,$D4,$E2,$9E,$F3,$32,$2E,$AA,$F8,$BB,$B3,$F6,$3A,$CC,$08
|
||||||
|
.byte $64,$8B,$C2,$5F,$58,$66,$AF,$67,$B3,$44,$2C,$66,$72,$E7,$3B,$3F
|
||||||
|
.byte $5B,$87,$0C,$17,$58,$E2,$B4,$A0,$70,$18,$81,$E6,$42,$56,$12,$CE
|
||||||
|
.byte $BB,$13,$46,$3C,$BE,$5A,$FB,$53
|
||||||
|
|
@ -0,0 +1,315 @@
|
||||||
|
; Tests most register instructions.
|
||||||
|
; Takes 15 seconds.
|
||||||
|
|
||||||
|
;.define PRINT_CHECKSUMS 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "instr_test.s"
|
||||||
|
|
||||||
|
instrs:
|
||||||
|
.byte $CB,$40,0 ; BIT 0,B
|
||||||
|
.byte $CB,$41,0 ; BIT 0,C
|
||||||
|
.byte $CB,$42,0 ; BIT 0,D
|
||||||
|
.byte $CB,$43,0 ; BIT 0,E
|
||||||
|
.byte $CB,$44,0 ; BIT 0,H
|
||||||
|
.byte $CB,$45,0 ; BIT 0,L
|
||||||
|
.byte $CB,$47,0 ; BIT 0,A
|
||||||
|
|
||||||
|
.byte $CB,$48,0 ; BIT 1,B
|
||||||
|
.byte $CB,$49,0 ; BIT 1,C
|
||||||
|
.byte $CB,$4A,0 ; BIT 1,D
|
||||||
|
.byte $CB,$4B,0 ; BIT 1,E
|
||||||
|
.byte $CB,$4C,0 ; BIT 1,H
|
||||||
|
.byte $CB,$4D,0 ; BIT 1,L
|
||||||
|
.byte $CB,$4F,0 ; BIT 1,A
|
||||||
|
|
||||||
|
.byte $CB,$50,0 ; BIT 2,B
|
||||||
|
.byte $CB,$51,0 ; BIT 2,C
|
||||||
|
.byte $CB,$52,0 ; BIT 2,D
|
||||||
|
.byte $CB,$53,0 ; BIT 2,E
|
||||||
|
.byte $CB,$54,0 ; BIT 2,H
|
||||||
|
.byte $CB,$55,0 ; BIT 2,L
|
||||||
|
.byte $CB,$57,0 ; BIT 2,A
|
||||||
|
|
||||||
|
.byte $CB,$58,0 ; BIT 3,B
|
||||||
|
.byte $CB,$59,0 ; BIT 3,C
|
||||||
|
.byte $CB,$5A,0 ; BIT 3,D
|
||||||
|
.byte $CB,$5B,0 ; BIT 3,E
|
||||||
|
.byte $CB,$5C,0 ; BIT 3,H
|
||||||
|
.byte $CB,$5D,0 ; BIT 3,L
|
||||||
|
.byte $CB,$5F,0 ; BIT 3,A
|
||||||
|
|
||||||
|
.byte $CB,$60,0 ; BIT 4,B
|
||||||
|
.byte $CB,$61,0 ; BIT 4,C
|
||||||
|
.byte $CB,$62,0 ; BIT 4,D
|
||||||
|
.byte $CB,$63,0 ; BIT 4,E
|
||||||
|
.byte $CB,$64,0 ; BIT 4,H
|
||||||
|
.byte $CB,$65,0 ; BIT 4,L
|
||||||
|
.byte $CB,$67,0 ; BIT 4,A
|
||||||
|
|
||||||
|
.byte $CB,$68,0 ; BIT 5,B
|
||||||
|
.byte $CB,$69,0 ; BIT 5,C
|
||||||
|
.byte $CB,$6A,0 ; BIT 5,D
|
||||||
|
.byte $CB,$6B,0 ; BIT 5,E
|
||||||
|
.byte $CB,$6C,0 ; BIT 5,H
|
||||||
|
.byte $CB,$6D,0 ; BIT 5,L
|
||||||
|
.byte $CB,$6F,0 ; BIT 5,A
|
||||||
|
|
||||||
|
.byte $CB,$70,0 ; BIT 6,B
|
||||||
|
.byte $CB,$71,0 ; BIT 6,C
|
||||||
|
.byte $CB,$72,0 ; BIT 6,D
|
||||||
|
.byte $CB,$73,0 ; BIT 6,E
|
||||||
|
.byte $CB,$74,0 ; BIT 6,H
|
||||||
|
.byte $CB,$75,0 ; BIT 6,L
|
||||||
|
.byte $CB,$77,0 ; BIT 6,A
|
||||||
|
|
||||||
|
.byte $CB,$78,0 ; BIT 7,B
|
||||||
|
.byte $CB,$79,0 ; BIT 7,C
|
||||||
|
.byte $CB,$7A,0 ; BIT 7,D
|
||||||
|
.byte $CB,$7B,0 ; BIT 7,E
|
||||||
|
.byte $CB,$7C,0 ; BIT 7,H
|
||||||
|
.byte $CB,$7D,0 ; BIT 7,L
|
||||||
|
.byte $CB,$7F,0 ; BIT 7,A
|
||||||
|
|
||||||
|
.byte $CB,$80,0 ; RES 0,B
|
||||||
|
.byte $CB,$81,0 ; RES 0,C
|
||||||
|
.byte $CB,$82,0 ; RES 0,D
|
||||||
|
.byte $CB,$83,0 ; RES 0,E
|
||||||
|
.byte $CB,$84,0 ; RES 0,H
|
||||||
|
.byte $CB,$85,0 ; RES 0,L
|
||||||
|
.byte $CB,$87,0 ; RES 0,A
|
||||||
|
|
||||||
|
.byte $CB,$88,0 ; RES 1,B
|
||||||
|
.byte $CB,$89,0 ; RES 1,C
|
||||||
|
.byte $CB,$8A,0 ; RES 1,D
|
||||||
|
.byte $CB,$8B,0 ; RES 1,E
|
||||||
|
.byte $CB,$8C,0 ; RES 1,H
|
||||||
|
.byte $CB,$8D,0 ; RES 1,L
|
||||||
|
.byte $CB,$8F,0 ; RES 1,A
|
||||||
|
|
||||||
|
.byte $CB,$90,0 ; RES 2,B
|
||||||
|
.byte $CB,$91,0 ; RES 2,C
|
||||||
|
.byte $CB,$92,0 ; RES 2,D
|
||||||
|
.byte $CB,$93,0 ; RES 2,E
|
||||||
|
.byte $CB,$94,0 ; RES 2,H
|
||||||
|
.byte $CB,$95,0 ; RES 2,L
|
||||||
|
.byte $CB,$97,0 ; RES 2,A
|
||||||
|
|
||||||
|
.byte $CB,$98,0 ; RES 3,B
|
||||||
|
.byte $CB,$99,0 ; RES 3,C
|
||||||
|
.byte $CB,$9A,0 ; RES 3,D
|
||||||
|
.byte $CB,$9B,0 ; RES 3,E
|
||||||
|
.byte $CB,$9C,0 ; RES 3,H
|
||||||
|
.byte $CB,$9D,0 ; RES 3,L
|
||||||
|
.byte $CB,$9F,0 ; RES 3,A
|
||||||
|
|
||||||
|
.byte $CB,$A0,0 ; RES 4,B
|
||||||
|
.byte $CB,$A1,0 ; RES 4,C
|
||||||
|
.byte $CB,$A2,0 ; RES 4,D
|
||||||
|
.byte $CB,$A3,0 ; RES 4,E
|
||||||
|
.byte $CB,$A4,0 ; RES 4,H
|
||||||
|
.byte $CB,$A5,0 ; RES 4,L
|
||||||
|
.byte $CB,$A7,0 ; RES 4,A
|
||||||
|
|
||||||
|
.byte $CB,$A8,0 ; RES 5,B
|
||||||
|
.byte $CB,$A9,0 ; RES 5,C
|
||||||
|
.byte $CB,$AA,0 ; RES 5,D
|
||||||
|
.byte $CB,$AB,0 ; RES 5,E
|
||||||
|
.byte $CB,$AC,0 ; RES 5,H
|
||||||
|
.byte $CB,$AD,0 ; RES 5,L
|
||||||
|
.byte $CB,$AF,0 ; RES 5,A
|
||||||
|
|
||||||
|
.byte $CB,$B0,0 ; RES 6,B
|
||||||
|
.byte $CB,$B1,0 ; RES 6,C
|
||||||
|
.byte $CB,$B2,0 ; RES 6,D
|
||||||
|
.byte $CB,$B3,0 ; RES 6,E
|
||||||
|
.byte $CB,$B4,0 ; RES 6,H
|
||||||
|
.byte $CB,$B5,0 ; RES 6,L
|
||||||
|
.byte $CB,$B7,0 ; RES 6,A
|
||||||
|
|
||||||
|
.byte $CB,$B8,0 ; RES 7,B
|
||||||
|
.byte $CB,$B9,0 ; RES 7,C
|
||||||
|
.byte $CB,$BA,0 ; RES 7,D
|
||||||
|
.byte $CB,$BB,0 ; RES 7,E
|
||||||
|
.byte $CB,$BC,0 ; RES 7,H
|
||||||
|
.byte $CB,$BD,0 ; RES 7,L
|
||||||
|
.byte $CB,$BF,0 ; RES 7,A
|
||||||
|
|
||||||
|
.byte $CB,$C0,0 ; SET 0,B
|
||||||
|
.byte $CB,$C1,0 ; SET 0,C
|
||||||
|
.byte $CB,$C2,0 ; SET 0,D
|
||||||
|
.byte $CB,$C3,0 ; SET 0,E
|
||||||
|
.byte $CB,$C4,0 ; SET 0,H
|
||||||
|
.byte $CB,$C5,0 ; SET 0,L
|
||||||
|
.byte $CB,$C7,0 ; SET 0,A
|
||||||
|
|
||||||
|
.byte $CB,$C8,0 ; SET 1,B
|
||||||
|
.byte $CB,$C9,0 ; SET 1,C
|
||||||
|
.byte $CB,$CA,0 ; SET 1,D
|
||||||
|
.byte $CB,$CB,0 ; SET 1,E
|
||||||
|
.byte $CB,$CC,0 ; SET 1,H
|
||||||
|
.byte $CB,$CD,0 ; SET 1,L
|
||||||
|
.byte $CB,$CF,0 ; SET 1,A
|
||||||
|
|
||||||
|
.byte $CB,$D0,0 ; SET 2,B
|
||||||
|
.byte $CB,$D1,0 ; SET 2,C
|
||||||
|
.byte $CB,$D2,0 ; SET 2,D
|
||||||
|
.byte $CB,$D3,0 ; SET 2,E
|
||||||
|
.byte $CB,$D4,0 ; SET 2,H
|
||||||
|
.byte $CB,$D5,0 ; SET 2,L
|
||||||
|
.byte $CB,$D7,0 ; SET 2,A
|
||||||
|
|
||||||
|
.byte $CB,$D8,0 ; SET 3,B
|
||||||
|
.byte $CB,$D9,0 ; SET 3,C
|
||||||
|
.byte $CB,$DA,0 ; SET 3,D
|
||||||
|
.byte $CB,$DB,0 ; SET 3,E
|
||||||
|
.byte $CB,$DC,0 ; SET 3,H
|
||||||
|
.byte $CB,$DD,0 ; SET 3,L
|
||||||
|
.byte $CB,$DF,0 ; SET 3,A
|
||||||
|
|
||||||
|
.byte $CB,$E0,0 ; SET 4,B
|
||||||
|
.byte $CB,$E1,0 ; SET 4,C
|
||||||
|
.byte $CB,$E2,0 ; SET 4,D
|
||||||
|
.byte $CB,$E3,0 ; SET 4,E
|
||||||
|
.byte $CB,$E4,0 ; SET 4,H
|
||||||
|
.byte $CB,$E5,0 ; SET 4,L
|
||||||
|
.byte $CB,$E7,0 ; SET 4,A
|
||||||
|
|
||||||
|
.byte $CB,$E8,0 ; SET 5,B
|
||||||
|
.byte $CB,$E9,0 ; SET 5,C
|
||||||
|
.byte $CB,$EA,0 ; SET 5,D
|
||||||
|
.byte $CB,$EB,0 ; SET 5,E
|
||||||
|
.byte $CB,$EC,0 ; SET 5,H
|
||||||
|
.byte $CB,$ED,0 ; SET 5,L
|
||||||
|
.byte $CB,$EF,0 ; SET 5,A
|
||||||
|
|
||||||
|
.byte $CB,$F0,0 ; SET 6,B
|
||||||
|
.byte $CB,$F1,0 ; SET 6,C
|
||||||
|
.byte $CB,$F2,0 ; SET 6,D
|
||||||
|
.byte $CB,$F3,0 ; SET 6,E
|
||||||
|
.byte $CB,$F4,0 ; SET 6,H
|
||||||
|
.byte $CB,$F5,0 ; SET 6,L
|
||||||
|
.byte $CB,$F7,0 ; SET 6,A
|
||||||
|
|
||||||
|
.byte $CB,$F8,0 ; SET 7,B
|
||||||
|
.byte $CB,$F9,0 ; SET 7,C
|
||||||
|
.byte $CB,$FA,0 ; SET 7,D
|
||||||
|
.byte $CB,$FB,0 ; SET 7,E
|
||||||
|
.byte $CB,$FC,0 ; SET 7,H
|
||||||
|
.byte $CB,$FD,0 ; SET 7,L
|
||||||
|
.byte $CB,$FF,0 ; SET 7,A
|
||||||
|
instrs_end:
|
||||||
|
|
||||||
|
test_instr:
|
||||||
|
ld c,$00
|
||||||
|
call test
|
||||||
|
ld c,$F0
|
||||||
|
call test
|
||||||
|
ret
|
||||||
|
|
||||||
|
test:
|
||||||
|
; Go through each value for A
|
||||||
|
ld hl,values
|
||||||
|
a_loop:
|
||||||
|
ld b,(hl)
|
||||||
|
push hl
|
||||||
|
|
||||||
|
; Go through each value for other registers
|
||||||
|
ld hl,values
|
||||||
|
values_loop:
|
||||||
|
push bc
|
||||||
|
push hl
|
||||||
|
|
||||||
|
push bc
|
||||||
|
|
||||||
|
; BC
|
||||||
|
ld a,(hl+)
|
||||||
|
ld b,a
|
||||||
|
ld a,(hl+)
|
||||||
|
ld c,a
|
||||||
|
|
||||||
|
; HL
|
||||||
|
ld a,(hl+)
|
||||||
|
ld d,a
|
||||||
|
ld a,(hl+)
|
||||||
|
ld e,a
|
||||||
|
push de
|
||||||
|
|
||||||
|
; DE
|
||||||
|
ld a,(hl+)
|
||||||
|
ld d,a
|
||||||
|
ld a,(hl+)
|
||||||
|
ld e,a
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop af
|
||||||
|
|
||||||
|
; call print_regs
|
||||||
|
jp instr
|
||||||
|
instr_done:
|
||||||
|
|
||||||
|
; Checksum registers
|
||||||
|
call checksum_af_bc_de_hl
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop bc
|
||||||
|
inc hl
|
||||||
|
ld a,l
|
||||||
|
cp <values_end
|
||||||
|
jr nz,values_loop
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
inc hl
|
||||||
|
ld a,l
|
||||||
|
cp <values_end
|
||||||
|
jr nz,a_loop
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
values:
|
||||||
|
.byte $00,$01,$02,$04,$08,$10,$20,$40,$80,$FF
|
||||||
|
values_end:
|
||||||
|
.byte $00,$01,$02,$04,$08,$10,$20,$40,$80,$FF
|
||||||
|
|
||||||
|
checksums:
|
||||||
|
.byte $46,$51,$4A,$16,$D4,$18,$B2,$4E,$ED,$B5,$15,$EA,$74,$66,$66,$3E
|
||||||
|
.byte $C2,$F3,$7F,$6A,$63,$CA,$62,$21,$72,$1E,$E4,$83,$6A,$56,$41,$1D
|
||||||
|
.byte $91,$90,$DB,$38,$54,$0A,$6C,$24,$02,$9E,$EA,$5B,$6D,$A7,$CB,$80
|
||||||
|
.byte $B4,$0B,$F3,$0F,$40,$38,$75,$BB,$AF,$30,$2B,$E5,$BD,$97,$D0,$33
|
||||||
|
.byte $83,$CB,$FD,$0A,$BB,$21,$93,$95,$28,$2F,$A2,$F6,$1B,$5F,$47,$E5
|
||||||
|
.byte $A3,$2E,$39,$63,$6C,$E0,$02,$BB,$78,$F1,$BA,$CB,$2C,$9F,$49,$E0
|
||||||
|
.byte $6C,$E0,$02,$BB,$04,$28,$A9,$FD,$5E,$D7,$2E,$93,$1B,$78,$08,$00
|
||||||
|
.byte $83,$CB,$FD,$0A,$BB,$21,$93,$95,$69,$17,$20,$96,$C3,$B4,$B6,$51
|
||||||
|
.byte $C1,$4E,$C3,$05,$72,$D0,$25,$98,$44,$F0,$99,$B7,$B4,$0B,$F3,$0F
|
||||||
|
.byte $54,$0A,$6C,$24,$45,$10,$2B,$9D,$86,$3C,$DF,$27,$02,$9E,$EA,$5B
|
||||||
|
.byte $B7,$B6,$4F,$60,$70,$E0,$E1,$AA,$C2,$F3,$7F,$6A,$63,$CA,$62,$21
|
||||||
|
.byte $80,$76,$41,$65,$AA,$3B,$D4,$2C,$ED,$B5,$15,$EA,$74,$66,$66,$3E
|
||||||
|
.byte $AD,$FF,$A0,$43,$7B,$4C,$06,$A4,$15,$32,$EE,$44,$43,$A6,$68,$3B
|
||||||
|
.byte $6F,$5D,$BE,$D4,$DA,$75,$1B,$EF,$9B,$4D,$99,$8F,$49,$E8,$A9,$1D
|
||||||
|
.byte $F5,$1B,$58,$3A,$92,$25,$2D,$51,$38,$5C,$62,$05,$DD,$A9,$63,$AD
|
||||||
|
.byte $E3,$78,$2F,$37,$90,$15,$DB,$62,$58,$E2,$E8,$35,$BB,$C1,$5A,$EA
|
||||||
|
.byte $06,$FE,$28,$AA,$4F,$5D,$64,$BF,$83,$CF,$7F,$B2,$F9,$A9,$90,$BF
|
||||||
|
.byte $DD,$06,$B6,$64,$25,$8A,$E0,$24,$FA,$40,$95,$13,$91,$61,$93,$0D
|
||||||
|
.byte $69,$A8,$0E,$0B,$AE,$FD,$DF,$1A,$D4,$98,$D8,$11,$61,$E9,$16,$66
|
||||||
|
.byte $BD,$82,$1F,$2C,$E2,$74,$26,$77,$13,$E4,$6A,$25,$D7,$DE,$8A,$4F
|
||||||
|
.byte $1F,$7B,$47,$BC,$DA,$DB,$31,$E7,$2B,$06,$2C,$39,$15,$FC,$1C,$0B
|
||||||
|
.byte $1A,$3B,$A0,$0F,$55,$E5,$D8,$1C,$6D,$6C,$7F,$B8,$14,$AD,$9C,$AF
|
||||||
|
.byte $92,$B6,$60,$40,$76,$E6,$6D,$2F,$9E,$CA,$45,$6D,$54,$97,$47,$35
|
||||||
|
.byte $EE,$39,$50,$63,$47,$8C,$8A,$AB,$18,$F7,$6D,$10,$B7,$A6,$74,$0C
|
||||||
|
.byte $11,$24,$9C,$F5,$64,$5D,$FB,$16,$65,$1C,$59,$C6,$B9,$E3,$30,$52
|
||||||
|
.byte $1D,$E4,$B8,$9E,$A3,$2F,$7B,$6F,$03,$20,$24,$41,$4C,$F7,$22,$B8
|
||||||
|
.byte $92,$A7,$75,$E3,$1D,$F2,$5E,$FD,$B7,$A4,$F3,$34,$BF,$F7,$37,$CA
|
||||||
|
.byte $67,$22,$D4,$4D,$DE,$1A,$99,$58,$B2,$65,$91,$12,$F2,$8C,$65,$08
|
||||||
|
.byte $69,$E2,$9B,$D3,$94,$8C,$71,$F1,$D8,$22,$29,$53,$E8,$6A,$D9,$55
|
||||||
|
.byte $3E,$24,$42,$EF,$38,$12,$AC,$02,$35,$84,$7D,$2C,$C2,$34,$AC,$E2
|
||||||
|
.byte $4B,$AA,$E0,$31,$8F,$A0,$F2,$13,$A8,$4F,$7B,$98,$02,$16,$3B,$D4
|
||||||
|
.byte $8D,$09,$58,$A4,$FF,$46,$CA,$17,$08,$AA,$78,$02,$4A,$CF,$72,$E1
|
||||||
|
.byte $A8,$55,$52,$89,$F8,$FD,$D6,$4E,$22,$E7,$8F,$C6,$80,$F1,$BB,$3C
|
||||||
|
.byte $09,$1B,$4A,$4A,$06,$A1,$FD,$54,$E4,$BF,$D8,$27,$14,$23,$42,$90
|
||||||
|
.byte $B3,$7B,$55,$14,$77,$22,$EE,$92,$E9,$37,$76,$8C,$7D,$CF,$B7,$C7
|
||||||
|
.byte $D2,$90,$17,$48,$BB,$52,$BC,$19,$AA,$91,$9F,$DC,$0D,$AA,$C9,$24
|
||||||
|
.byte $C8,$45,$DF,$AB,$B3,$83,$A8,$9E,$0F,$AA,$62,$2F,$C4,$C0,$28,$BA
|
||||||
|
.byte $32,$56,$99,$69,$C9,$77,$4B,$62,$6B,$FF,$B6,$DD,$42,$46,$7A,$00
|
||||||
|
.byte $DA,$E9,$67,$4D,$46,$9C,$B5,$92,$04,$B5,$F6,$03,$01,$3C,$A2,$47
|
||||||
|
.byte $40,$15,$4A,$D6,$04,$39,$BC,$2F,$E9,$E1,$39,$59,$9B,$6A,$A4,$12
|
||||||
|
.byte $97,$23,$99,$30,$9E,$A6,$70,$AD,$C7,$1B,$D6,$1F,$05,$15,$D2,$5B
|
||||||
|
.byte $29,$0F,$5A,$CC,$0A,$99,$A2,$68,$5D,$58,$ED,$9C,$B9,$82,$CD,$74
|
||||||
|
|
@ -0,0 +1,162 @@
|
||||||
|
; Tests (HL/BC/DE) instructions.
|
||||||
|
; Takes 20 seconds.
|
||||||
|
|
||||||
|
;.define PRINT_CHECKSUMS 1
|
||||||
|
.include "shell.inc"
|
||||||
|
.include "instr_test.s"
|
||||||
|
|
||||||
|
instrs:
|
||||||
|
.byte $0A,0,0 ; LD A,(BC)
|
||||||
|
.byte $1A,0,0 ; LD A,(DE)
|
||||||
|
.byte $02,0,0 ; LD (BC),A
|
||||||
|
.byte $12,0,0 ; LD (DE),A
|
||||||
|
.byte $2A,0,0 ; LD A,(HL+)
|
||||||
|
.byte $3A,0,0 ; LD A,(HL-)
|
||||||
|
.byte $22,0,0 ; LD (HL+),A
|
||||||
|
.byte $32,0,0 ; LD (HL-),A
|
||||||
|
.byte $B6,0,0 ; OR (HL)
|
||||||
|
.byte $BE,0,0 ; CP (HL)
|
||||||
|
.byte $86,0,0 ; ADD (HL)
|
||||||
|
.byte $8E,0,0 ; ADC (HL)
|
||||||
|
.byte $96,0,0 ; SUB (HL)
|
||||||
|
.byte $9E,0,0 ; SBC (HL)
|
||||||
|
.byte $A6,0,0 ; AND (HL)
|
||||||
|
.byte $AE,0,0 ; XOR (HL)
|
||||||
|
.byte $35,0,0 ; DEC (HL)
|
||||||
|
.byte $34,0,0 ; INC (HL)
|
||||||
|
.byte $CB,$06,0 ; RLC (HL)
|
||||||
|
.byte $CB,$0E,0 ; RRC (HL)
|
||||||
|
.byte $CB,$16,0 ; RL (HL)
|
||||||
|
.byte $CB,$1E,0 ; RR (HL)
|
||||||
|
.byte $CB,$26,0 ; SLA (HL)
|
||||||
|
.byte $CB,$2E,0 ; SRA (HL)
|
||||||
|
.byte $CB,$36,0 ; SWAP (HL)
|
||||||
|
.byte $CB,$3E,0 ; SRL (HL)
|
||||||
|
.byte $CB,$46,0 ; BIT 0,(HL)
|
||||||
|
.byte $CB,$4E,0 ; BIT 1,(HL)
|
||||||
|
.byte $CB,$56,0 ; BIT 2,(HL)
|
||||||
|
.byte $CB,$5E,0 ; BIT 3,(HL)
|
||||||
|
.byte $CB,$66,0 ; BIT 4,(HL)
|
||||||
|
.byte $CB,$6E,0 ; BIT 5,(HL)
|
||||||
|
.byte $CB,$76,0 ; BIT 6,(HL)
|
||||||
|
.byte $CB,$7E,0 ; BIT 7,(HL)
|
||||||
|
.byte $CB,$86,0 ; RES 0,(HL)
|
||||||
|
.byte $CB,$8E,0 ; RES 1,(HL)
|
||||||
|
.byte $CB,$96,0 ; RES 2,(HL)
|
||||||
|
.byte $CB,$9E,0 ; RES 3,(HL)
|
||||||
|
.byte $CB,$A6,0 ; RES 4,(HL)
|
||||||
|
.byte $CB,$AE,0 ; RES 5,(HL)
|
||||||
|
.byte $CB,$B6,0 ; RES 6,(HL)
|
||||||
|
.byte $CB,$BE,0 ; RES 7,(HL)
|
||||||
|
.byte $CB,$C6,0 ; SET 0,(HL)
|
||||||
|
.byte $CB,$CE,0 ; SET 1,(HL)
|
||||||
|
.byte $CB,$D6,0 ; SET 2,(HL)
|
||||||
|
.byte $CB,$DE,0 ; SET 3,(HL)
|
||||||
|
.byte $CB,$E6,0 ; SET 4,(HL)
|
||||||
|
.byte $CB,$EE,0 ; SET 5,(HL)
|
||||||
|
.byte $CB,$F6,0 ; SET 6,(HL)
|
||||||
|
.byte $CB,$FE,0 ; SET 7,(HL)
|
||||||
|
.byte $27,0,0 ; DAA
|
||||||
|
instrs_end:
|
||||||
|
|
||||||
|
test_instr:
|
||||||
|
ld c,$00
|
||||||
|
call test
|
||||||
|
ld c,$10
|
||||||
|
call test
|
||||||
|
ld c,$E0
|
||||||
|
call test
|
||||||
|
ld c,$F0
|
||||||
|
call test
|
||||||
|
ret
|
||||||
|
|
||||||
|
test:
|
||||||
|
; Go through each value for A
|
||||||
|
ld hl,values
|
||||||
|
a_loop:
|
||||||
|
ld b,(hl)
|
||||||
|
push hl
|
||||||
|
|
||||||
|
; Go through each value for (HL)
|
||||||
|
ld hl,values
|
||||||
|
values_loop:
|
||||||
|
push bc
|
||||||
|
push hl
|
||||||
|
|
||||||
|
push bc
|
||||||
|
|
||||||
|
; BC
|
||||||
|
ld a,(hl+)
|
||||||
|
ld bc,rp_temp
|
||||||
|
ld (rp_temp),a
|
||||||
|
|
||||||
|
; DE
|
||||||
|
ld a,(hl+)
|
||||||
|
ld de,rp_temp+1
|
||||||
|
ld (rp_temp+1),a
|
||||||
|
|
||||||
|
; HL
|
||||||
|
ld a,(hl)
|
||||||
|
ld hl,rp_temp+2
|
||||||
|
ld (rp_temp+2),a
|
||||||
|
|
||||||
|
; AF
|
||||||
|
pop af
|
||||||
|
|
||||||
|
; call print_regs
|
||||||
|
jp instr
|
||||||
|
instr_done:
|
||||||
|
|
||||||
|
; Checksum AF, HL, and (HL)
|
||||||
|
push hl
|
||||||
|
push af
|
||||||
|
call update_crc_fast
|
||||||
|
pop hl
|
||||||
|
ld a,l
|
||||||
|
call update_crc_fast
|
||||||
|
pop bc
|
||||||
|
ld a,b
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,c
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,(rp_temp)
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,(rp_temp+1)
|
||||||
|
call update_crc_fast
|
||||||
|
ld a,(rp_temp+2)
|
||||||
|
call update_crc_fast
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop bc
|
||||||
|
inc hl
|
||||||
|
ld a,l
|
||||||
|
cp <values_end
|
||||||
|
jr nz,values_loop
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
inc hl
|
||||||
|
ld a,l
|
||||||
|
cp <values_end
|
||||||
|
jr nz,a_loop
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
values:
|
||||||
|
.byte $00,$01,$0F,$10,$1F,$7F,$80,$F0,$FF,$02,$04,$08,$20,$40
|
||||||
|
values_end:
|
||||||
|
.byte $00,$01,$0F,$10,$1F,$7F,$80,$F0,$FF,$02,$04,$08,$20,$40
|
||||||
|
|
||||||
|
checksums:
|
||||||
|
.byte $E0,$E5,$09,$A7,$FB,$28,$0D,$AE,$AC,$BB,$91,$D8,$B3,$E2,$AF,$C4
|
||||||
|
.byte $3D,$B5,$02,$07,$4F,$6E,$5B,$7E,$AE,$02,$E7,$14,$DC,$D9,$BE,$6D
|
||||||
|
.byte $F1,$48,$A9,$42,$67,$08,$FE,$57,$06,$6A,$A9,$B1,$FD,$A5,$84,$F0
|
||||||
|
.byte $82,$FC,$24,$A9,$A8,$1D,$BB,$E2,$F8,$23,$8C,$DE,$0E,$1D,$64,$D1
|
||||||
|
.byte $05,$E0,$24,$41,$53,$75,$47,$55,$F4,$D9,$10,$6A,$38,$16,$28,$D8
|
||||||
|
.byte $D1,$28,$A3,$E0,$A2,$05,$B8,$FE,$B0,$F4,$F5,$8F,$4B,$39,$03,$B0
|
||||||
|
.byte $8A,$07,$BA,$90,$25,$99,$A7,$78,$E6,$9A,$D1,$49,$C9,$B2,$A3,$E5
|
||||||
|
.byte $36,$34,$CB,$5A,$97,$42,$71,$09,$39,$87,$25,$EC,$54,$EE,$C5,$B3
|
||||||
|
.byte $FC,$B5,$6F,$BD,$0B,$D8,$46,$6F,$6A,$27,$81,$9F,$F8,$38,$E2,$71
|
||||||
|
.byte $55,$19,$21,$83,$4B,$85,$9F,$4B,$A1,$78,$14,$60,$58,$08,$D9,$57
|
||||||
|
.byte $11,$8C,$83,$9A,$9F,$01,$D1,$90,$E8,$82,$0B,$5A,$BD,$75,$86,$21
|
||||||
|
.byte $DF,$83,$E9,$23,$1E,$B6,$7F,$D1,$4A,$18,$A5,$8E,$CF,$CF,$CA,$51
|
||||||
|
.byte $3F,$03,$A4,$96,$C3,$1F,$9E,$88,$0C,$DF,$1F,$B1
|
||||||
|
|
@ -0,0 +1,215 @@
|
||||||
|
; Sound chip utilities
|
||||||
|
|
||||||
|
; Turns APU off
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
sound_off:
|
||||||
|
wreg NR52,0
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Turns APU on
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
sound_on:
|
||||||
|
wreg NR52,$80 ; power
|
||||||
|
wreg NR51,$FF ; mono
|
||||||
|
wreg NR50,$77 ; volume
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Synchronizes to APU length counter within
|
||||||
|
; tens of clocks. Uses square 2 channel.
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
sync_apu:
|
||||||
|
wreg NR24,$00 ; disable length
|
||||||
|
wreg NR21,$3E ; length = 2 (in case of extra len clk)
|
||||||
|
wreg NR22,$08 ; silent without disabling channel
|
||||||
|
wreg NR24,$C0 ; start length
|
||||||
|
- lda NR52 ; wait for length to reach zero
|
||||||
|
and $02
|
||||||
|
jr nz,-
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Synchronizes to first square sweep within
|
||||||
|
; tens of clocks. Uses square 1 channel.
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
sync_sweep:
|
||||||
|
wreg NR10,$11 ; sweep period = 1, shift = 1
|
||||||
|
wreg NR12,$08 ; silent without disabling channel
|
||||||
|
wreg NR13,$FF ; freq = $3FF
|
||||||
|
wreg NR14,$83 ; start
|
||||||
|
- lda NR52
|
||||||
|
and $01
|
||||||
|
jr nz,-
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Copies 16-byte wave from (HL) to wave RAM
|
||||||
|
; Preserved: BC, DE
|
||||||
|
load_wave:
|
||||||
|
push bc
|
||||||
|
wreg NR30,$00 ; disable while writing
|
||||||
|
ld c,$30
|
||||||
|
- ld a,(hl+)
|
||||||
|
ld ($FF00+c),a
|
||||||
|
inc c
|
||||||
|
bit 6,c
|
||||||
|
jr z,-
|
||||||
|
pop bc
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Makes short beep
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
beep:
|
||||||
|
xor a ; sound off
|
||||||
|
sta NR52
|
||||||
|
dec a
|
||||||
|
sta NR52 ; sound on
|
||||||
|
sta NR51 ; mono
|
||||||
|
sta NR50 ; volume
|
||||||
|
wreg NR12,$F1 ; volume, envelope rate
|
||||||
|
wreg NR14,$86 ; note on, pitch
|
||||||
|
delay_msec 250
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Marks sound with bits of A encoded into volume
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
mark_sound:
|
||||||
|
push bc
|
||||||
|
ld c,a
|
||||||
|
ld b,8
|
||||||
|
wreg NR10,0
|
||||||
|
wreg NR11,$80
|
||||||
|
wreg NR13,$F8
|
||||||
|
- ld a,$60
|
||||||
|
rl c
|
||||||
|
jr nc,+
|
||||||
|
ld a,$A0
|
||||||
|
+ sta NR12
|
||||||
|
wreg NR14,$87
|
||||||
|
delay_usec 300
|
||||||
|
wreg NR12,0
|
||||||
|
delay_usec 100
|
||||||
|
dec b
|
||||||
|
jr nz,-
|
||||||
|
pop bc
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Fills wave RAM with A
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
fill_wave:
|
||||||
|
push bc
|
||||||
|
ld c,$30
|
||||||
|
- ld ($FF00+c),a
|
||||||
|
inc c
|
||||||
|
bit 6,c
|
||||||
|
jr z,-
|
||||||
|
pop bc
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Gets current length counter value for
|
||||||
|
; channel with mask A into A. Length counter
|
||||||
|
; must be enabled for that channel.
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
get_len_a:
|
||||||
|
push bc
|
||||||
|
ld c,a
|
||||||
|
ld b,0
|
||||||
|
- lda NR52 ; 3
|
||||||
|
and c ; 1
|
||||||
|
jr z,+ ; 2
|
||||||
|
delay 4096-10
|
||||||
|
inc b ; 1
|
||||||
|
jr nz,- ; 3
|
||||||
|
+ ld a,b
|
||||||
|
pop bc
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Synchronizes exactly to length clock. Next length clock
|
||||||
|
; occurs by 4079 clocks after this returns. Uses NR2x.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
sync_length:
|
||||||
|
push af
|
||||||
|
push hl
|
||||||
|
|
||||||
|
ld hl,NR52
|
||||||
|
wreg NR22,$08 ; silent without disabling channel
|
||||||
|
wreg NR24,$40 ; avoids extra length clock on trigger
|
||||||
|
wreg NR21,-2 ; length = 2, in case clock occurs immediately
|
||||||
|
wreg NR24,$C0 ; start length
|
||||||
|
|
||||||
|
; Coarse sync
|
||||||
|
ld a,$02
|
||||||
|
- and (hl)
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
; Fine sync. Slowly moves "forward" until
|
||||||
|
; length clock occurs just before reading NR52.
|
||||||
|
- delay 4097-20
|
||||||
|
wreg NR21,-1 ; 5
|
||||||
|
wreg NR24,$C0 ; 5
|
||||||
|
lda NR52 ; 3
|
||||||
|
delay 2 ; 2
|
||||||
|
and $02 ; 2
|
||||||
|
jr nz,- ; 3
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Delays n*4096 cycles
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
.macro delay_frames ; n
|
||||||
|
ld a,\1
|
||||||
|
call delay_frames_
|
||||||
|
.endm
|
||||||
|
|
||||||
|
|
||||||
|
; Delays A*4096+13 cycles (including CALL)
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
delay_a_frames:
|
||||||
|
or a ; 1
|
||||||
|
jr nz,+ ; 3
|
||||||
|
; -1
|
||||||
|
ret
|
||||||
|
delay_frames_: ; delays 4096*A-2 cycles (including CALL)
|
||||||
|
push af ; 4
|
||||||
|
ld a,256-13-20-12 ; 2
|
||||||
|
jr ++ ; 3
|
||||||
|
+
|
||||||
|
- push af ; 4
|
||||||
|
ld a,256-13-20 ; 2
|
||||||
|
++ call delay_a_20_cycles
|
||||||
|
delay 4096-256
|
||||||
|
pop af ; 3
|
||||||
|
dec a ; 1
|
||||||
|
jr nz,- ; 3
|
||||||
|
; -1
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
.macro test_chan_timing ; chan, iter
|
||||||
|
ld a,\1
|
||||||
|
call print_dec
|
||||||
|
call print_space
|
||||||
|
ld a,\2
|
||||||
|
- push af
|
||||||
|
test_chan 1<<\1, \1*5+NR10
|
||||||
|
pop af
|
||||||
|
dec a
|
||||||
|
jr nz,-
|
||||||
|
call print_newline
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro test_chans ARGS iter
|
||||||
|
test_chan_timing 0,iter
|
||||||
|
test_chan_timing 1,iter
|
||||||
|
test_chan_timing 2,iter
|
||||||
|
test_chan_timing 3,iter
|
||||||
|
.endm
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
; Build as GBS music file
|
||||||
|
|
||||||
|
.memoryMap
|
||||||
|
defaultSlot 0
|
||||||
|
slot 0 $3000 size $1000
|
||||||
|
slot 1 $C000 size $1000
|
||||||
|
.endMe
|
||||||
|
|
||||||
|
.romBankSize $1000
|
||||||
|
.romBanks 2
|
||||||
|
|
||||||
|
|
||||||
|
;;;; GBS music file header
|
||||||
|
|
||||||
|
.byte "GBS"
|
||||||
|
.byte 1 ; vers
|
||||||
|
.byte 1 ; songs
|
||||||
|
.byte 1 ; first song
|
||||||
|
.word load_addr
|
||||||
|
.word reset
|
||||||
|
.word gbs_play
|
||||||
|
.word std_stack
|
||||||
|
.byte 0,0 ; timer
|
||||||
|
.ds $60,0
|
||||||
|
load_addr:
|
||||||
|
|
||||||
|
; WLA assumes we're building ROM and messes
|
||||||
|
; with bytes at the beginning, so skip them.
|
||||||
|
.ds $100,0
|
||||||
|
|
||||||
|
|
||||||
|
;;;; Shell
|
||||||
|
|
||||||
|
.include "runtime.s"
|
||||||
|
|
||||||
|
init_runtime:
|
||||||
|
ld a,$01 ; Identify as DMG hardware
|
||||||
|
ld (gb_id),a
|
||||||
|
.ifdef TEST_NAME
|
||||||
|
print_str TEST_NAME,newline,newline
|
||||||
|
.endif
|
||||||
|
ret
|
||||||
|
|
||||||
|
std_print:
|
||||||
|
sta SB
|
||||||
|
wreg SC,$81
|
||||||
|
delay 2304
|
||||||
|
ret
|
||||||
|
|
||||||
|
post_exit:
|
||||||
|
call play_byte
|
||||||
|
forever:
|
||||||
|
wreg NR52,0 ; sound off
|
||||||
|
- jp -
|
||||||
|
|
||||||
|
.ifndef CUSTOM_RESET
|
||||||
|
gbs_play:
|
||||||
|
.endif
|
||||||
|
console_flush:
|
||||||
|
console_normal:
|
||||||
|
console_inverse:
|
||||||
|
console_set_mode:
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Reports A in binary as high and low tones, with
|
||||||
|
; leading low tone for reference. Omits leading
|
||||||
|
; zeroes.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
play_byte:
|
||||||
|
push af
|
||||||
|
push hl
|
||||||
|
|
||||||
|
; HL = (A << 1) | 1
|
||||||
|
scf
|
||||||
|
rla
|
||||||
|
ld l,a
|
||||||
|
ld h,0
|
||||||
|
rl h
|
||||||
|
|
||||||
|
; Shift left until next-to-top bit is 1
|
||||||
|
- add hl,hl
|
||||||
|
bit 6,h
|
||||||
|
jr z,-
|
||||||
|
|
||||||
|
; Reset sound
|
||||||
|
delay_msec 400
|
||||||
|
wreg NR52,0 ; sound off
|
||||||
|
wreg NR52,$80 ; sound on
|
||||||
|
wreg NR51,$FF ; mono
|
||||||
|
wreg NR50,$77 ; volume
|
||||||
|
|
||||||
|
- add hl,hl
|
||||||
|
|
||||||
|
; Low or high pitch based on bit shifted out
|
||||||
|
; of HL
|
||||||
|
ld a,0
|
||||||
|
jr nc,+
|
||||||
|
ld a,$FF
|
||||||
|
+ sta NR23
|
||||||
|
|
||||||
|
; Play short tone
|
||||||
|
wreg NR21,$A0
|
||||||
|
wreg NR22,$F0
|
||||||
|
wreg NR24,$86
|
||||||
|
delay_msec 75
|
||||||
|
wreg NR22,0
|
||||||
|
wreg NR23,$F8
|
||||||
|
wreg NR24,$87
|
||||||
|
delay_msec 200
|
||||||
|
|
||||||
|
; Loop until HL = $8000
|
||||||
|
ld a,h
|
||||||
|
xor $80
|
||||||
|
or l
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
.ends
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
; Build as GB ROM
|
||||||
|
|
||||||
|
.memoryMap
|
||||||
|
defaultSlot 0
|
||||||
|
slot 0 $0000 size $4000
|
||||||
|
slot 1 $C000 size $4000
|
||||||
|
.endMe
|
||||||
|
|
||||||
|
.romBankSize $4000 ; generates $8000 byte ROM
|
||||||
|
.romBanks 2
|
||||||
|
|
||||||
|
.cartridgeType 1 ; MBC1
|
||||||
|
.computeChecksum
|
||||||
|
.computeComplementCheck
|
||||||
|
|
||||||
|
|
||||||
|
;;;; GB ROM header
|
||||||
|
|
||||||
|
; GB header read by bootrom
|
||||||
|
.org $100
|
||||||
|
nop
|
||||||
|
jp reset
|
||||||
|
|
||||||
|
; Nintendo logo required for proper boot
|
||||||
|
.byte $CE,$ED,$66,$66,$CC,$0D,$00,$0B
|
||||||
|
.byte $03,$73,$00,$83,$00,$0C,$00,$0D
|
||||||
|
.byte $00,$08,$11,$1F,$88,$89,$00,$0E
|
||||||
|
.byte $DC,$CC,$6E,$E6,$DD,$DD,$D9,$99
|
||||||
|
.byte $BB,$BB,$67,$63,$6E,$0E,$EC,$CC
|
||||||
|
.byte $DD,$DC,$99,$9F,$BB,$B9,$33,$3E
|
||||||
|
|
||||||
|
; Internal name
|
||||||
|
.ifdef ROM_NAME
|
||||||
|
.byte ROM_NAME
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; CGB/DMG requirements
|
||||||
|
.org $143
|
||||||
|
.ifdef REQUIRE_CGB
|
||||||
|
.byte $C0
|
||||||
|
.else
|
||||||
|
.ifndef REQUIRE_DMG
|
||||||
|
.byte $80
|
||||||
|
.endif
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.org $200
|
||||||
|
|
||||||
|
|
||||||
|
;;;; Shell
|
||||||
|
|
||||||
|
.include "runtime.s"
|
||||||
|
.include "console.s"
|
||||||
|
|
||||||
|
init_runtime:
|
||||||
|
call console_init
|
||||||
|
.ifdef TEST_NAME
|
||||||
|
print_str TEST_NAME,newline,newline
|
||||||
|
.endif
|
||||||
|
ret
|
||||||
|
|
||||||
|
std_print:
|
||||||
|
push af
|
||||||
|
sta SB
|
||||||
|
wreg SC,$81
|
||||||
|
delay 2304
|
||||||
|
pop af
|
||||||
|
jp console_print
|
||||||
|
|
||||||
|
post_exit:
|
||||||
|
call console_show
|
||||||
|
call play_byte
|
||||||
|
forever:
|
||||||
|
wreg NR52,0 ; sound off
|
||||||
|
- jr -
|
||||||
|
|
||||||
|
play_byte:
|
||||||
|
ret
|
||||||
|
|
||||||
|
.ends
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
; Multiple checksum table handling
|
||||||
|
|
||||||
|
.define next_checksum bss+0
|
||||||
|
.redefine bss bss+2
|
||||||
|
|
||||||
|
; If PRINT_CHECKSUMS is defined, checksums are printed
|
||||||
|
; rather than compared.
|
||||||
|
|
||||||
|
; Initializes multiple checksum handler to use checksums
|
||||||
|
; table (defined by user).
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
checksums_init:
|
||||||
|
ld a,<checksums
|
||||||
|
ld (next_checksum),a
|
||||||
|
ld a,>checksums
|
||||||
|
ld (next_checksum+1),a
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Compares current checksum with next checksum in
|
||||||
|
; list. Z if they match, NZ if not.
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
checksums_compare:
|
||||||
|
.ifdef PRINT_CHECKSUMS
|
||||||
|
lda checksum+3
|
||||||
|
push af
|
||||||
|
lda checksum+2
|
||||||
|
push af
|
||||||
|
lda checksum+1
|
||||||
|
push af
|
||||||
|
lda checksum+0
|
||||||
|
push af
|
||||||
|
|
||||||
|
ld a,(next_checksum)
|
||||||
|
inc a
|
||||||
|
ld (next_checksum),a
|
||||||
|
sub <checksums+1
|
||||||
|
and $03
|
||||||
|
ld a,','
|
||||||
|
jr nz,+
|
||||||
|
print_str newline,'.',"byte"
|
||||||
|
ld a,' '
|
||||||
|
+ call print_char
|
||||||
|
|
||||||
|
pop af
|
||||||
|
call @print_byte
|
||||||
|
pop af
|
||||||
|
call @print_byte
|
||||||
|
pop af
|
||||||
|
call @print_byte
|
||||||
|
ld a,'$'
|
||||||
|
call print_char
|
||||||
|
pop af
|
||||||
|
call print_hex
|
||||||
|
|
||||||
|
xor a
|
||||||
|
ret
|
||||||
|
|
||||||
|
@print_byte:
|
||||||
|
push af
|
||||||
|
ld a,'$'
|
||||||
|
call print_char
|
||||||
|
pop af
|
||||||
|
call print_hex
|
||||||
|
ld a,','
|
||||||
|
call print_char
|
||||||
|
ret
|
||||||
|
.else
|
||||||
|
|
||||||
|
push bc
|
||||||
|
push de
|
||||||
|
push hl
|
||||||
|
ld a,(next_checksum)
|
||||||
|
ld l,a
|
||||||
|
ld a,(next_checksum+1)
|
||||||
|
ld h,a
|
||||||
|
ld de,checksum
|
||||||
|
ld b,0
|
||||||
|
- ld a,(de)
|
||||||
|
xor (hl)
|
||||||
|
or b
|
||||||
|
ld b,a
|
||||||
|
inc hl
|
||||||
|
inc e
|
||||||
|
ld a,e
|
||||||
|
cp <(checksum+4)
|
||||||
|
jr nz,-
|
||||||
|
ld a,l
|
||||||
|
ld (next_checksum),a
|
||||||
|
ld a,h
|
||||||
|
ld (next_checksum+1),a
|
||||||
|
|
||||||
|
ld a,b
|
||||||
|
cp 0
|
||||||
|
pop hl
|
||||||
|
pop de
|
||||||
|
pop bc
|
||||||
|
ret
|
||||||
|
.endif
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,291 @@
|
||||||
|
; Scrolling text console
|
||||||
|
|
||||||
|
; Console is 20x18 characters. Buffers lines, so
|
||||||
|
; output doesn't appear until a newline or flush.
|
||||||
|
; If scrolling isn't supported (i.e. SCY is treated
|
||||||
|
; as if always zero), the first 18 lines will
|
||||||
|
; still print properly). Also works properly if
|
||||||
|
; LY isn't supported (always reads back as the same
|
||||||
|
; value).
|
||||||
|
|
||||||
|
.define console_width 20
|
||||||
|
|
||||||
|
.define console_buf bss+0
|
||||||
|
.define console_pos bss+console_width
|
||||||
|
.define console_mode bss+console_width+1
|
||||||
|
.define console_scroll bss+console_width+2
|
||||||
|
.redefine bss bss+console_width+3
|
||||||
|
|
||||||
|
|
||||||
|
; Waits for start of LCD blanking period
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
console_wait_vbl:
|
||||||
|
push bc
|
||||||
|
|
||||||
|
; Wait for start of vblank, with
|
||||||
|
; timeout in case LY doesn't work
|
||||||
|
; or LCD is disabled.
|
||||||
|
ld bc,-1250
|
||||||
|
- inc bc
|
||||||
|
ld a,b
|
||||||
|
or c
|
||||||
|
jr z,@timeout
|
||||||
|
lda LY
|
||||||
|
cp 144
|
||||||
|
jr nz,-
|
||||||
|
@timeout:
|
||||||
|
|
||||||
|
pop bc
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Initializes text console
|
||||||
|
console_init:
|
||||||
|
call console_hide
|
||||||
|
|
||||||
|
; CGB-specific inits
|
||||||
|
ld a,(gb_id)
|
||||||
|
and gb_id_cgb
|
||||||
|
call nz,@init_cgb
|
||||||
|
|
||||||
|
; Clear nametable
|
||||||
|
ld a,' '
|
||||||
|
call @fill_nametable
|
||||||
|
|
||||||
|
; Load tiles
|
||||||
|
ld hl,TILES+$200
|
||||||
|
ld c,0
|
||||||
|
call @load_tiles
|
||||||
|
ld hl,TILES+$A00
|
||||||
|
ld c,$FF
|
||||||
|
call @load_tiles
|
||||||
|
|
||||||
|
; Init state
|
||||||
|
ld a,console_width
|
||||||
|
ld (console_pos),a
|
||||||
|
ld a,0
|
||||||
|
ld (console_mode),a
|
||||||
|
ld a,-8
|
||||||
|
ld (console_scroll),a
|
||||||
|
call console_scroll_up_
|
||||||
|
jr console_show
|
||||||
|
|
||||||
|
@fill_nametable:
|
||||||
|
ld hl,BGMAP0
|
||||||
|
ld b,4
|
||||||
|
- ld (hl),a
|
||||||
|
inc l
|
||||||
|
jr nz,-
|
||||||
|
inc h
|
||||||
|
dec b
|
||||||
|
jr nz,-
|
||||||
|
ret
|
||||||
|
|
||||||
|
@init_cgb:
|
||||||
|
; Clear palette
|
||||||
|
wreg $FF68,$80
|
||||||
|
ld b,16
|
||||||
|
- wreg $FF69,$FF
|
||||||
|
wreg $FF69,$7F
|
||||||
|
wreg $FF69,$00
|
||||||
|
wreg $FF69,$00
|
||||||
|
wreg $FF69,$00
|
||||||
|
wreg $FF69,$00
|
||||||
|
wreg $FF69,$00
|
||||||
|
wreg $FF69,$00
|
||||||
|
dec b
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
; Clear attributes
|
||||||
|
ld a,1
|
||||||
|
ld (VBK),a
|
||||||
|
ld a,0
|
||||||
|
call @fill_nametable
|
||||||
|
|
||||||
|
ld a,0
|
||||||
|
ld (VBK),a
|
||||||
|
ret
|
||||||
|
|
||||||
|
@load_tiles:
|
||||||
|
ld de,ASCII
|
||||||
|
ld b,96
|
||||||
|
-- push bc
|
||||||
|
ld b,8
|
||||||
|
- ld a,(de)
|
||||||
|
inc de
|
||||||
|
xor c
|
||||||
|
ldi (hl),a
|
||||||
|
ldi (hl),a
|
||||||
|
dec b
|
||||||
|
jr nz,-
|
||||||
|
pop bc
|
||||||
|
dec b
|
||||||
|
jr nz,--
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Shows console display
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
console_show:
|
||||||
|
push af
|
||||||
|
|
||||||
|
; Enable LCD
|
||||||
|
call console_wait_vbl
|
||||||
|
wreg LCDC,$91
|
||||||
|
wreg SCX,0
|
||||||
|
wreg BGP,$E4
|
||||||
|
|
||||||
|
jp console_apply_scroll_
|
||||||
|
|
||||||
|
|
||||||
|
; Hides console display by turning LCD off
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
console_hide:
|
||||||
|
push af
|
||||||
|
|
||||||
|
; LCD off
|
||||||
|
call console_wait_vbl
|
||||||
|
wreg LCDC,$11
|
||||||
|
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Changes to normal text mode
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
console_normal:
|
||||||
|
xor a
|
||||||
|
jr console_set_mode
|
||||||
|
|
||||||
|
; Changes to inverse text mode
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
console_inverse:
|
||||||
|
ld a,$80
|
||||||
|
|
||||||
|
; Changes console mode to A.
|
||||||
|
; 0: Normal, $80: Inverse
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
console_set_mode:
|
||||||
|
and $80
|
||||||
|
ld (console_mode),a
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Prints char A to console. Will not appear until
|
||||||
|
; a newline or flush occurs.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
console_print:
|
||||||
|
push af
|
||||||
|
|
||||||
|
cp 10
|
||||||
|
jr z,console_newline_
|
||||||
|
|
||||||
|
push hl
|
||||||
|
push af
|
||||||
|
ld hl,console_pos
|
||||||
|
ldi a,(hl)
|
||||||
|
cp <console_buf
|
||||||
|
jr nz,@not_at_end
|
||||||
|
|
||||||
|
; Newline if at end of current line. If this
|
||||||
|
; were done after writing to buffer, calling
|
||||||
|
; console_newline would print extra newline.
|
||||||
|
; Doing it before eliminates this.
|
||||||
|
|
||||||
|
; Ignore any spaces at end of line
|
||||||
|
pop af
|
||||||
|
cp ' '
|
||||||
|
jr z,@ignore_space
|
||||||
|
call console_newline
|
||||||
|
push af
|
||||||
|
|
||||||
|
@not_at_end:
|
||||||
|
pop af
|
||||||
|
or (hl) ; apply current attributes
|
||||||
|
dec l ; hl = console_pos
|
||||||
|
dec (hl) ; console_pos = console_pos - 1
|
||||||
|
ld l,(hl) ; hl = position in buffer
|
||||||
|
ld (hl),a
|
||||||
|
|
||||||
|
@ignore_space
|
||||||
|
pop hl
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Displays current line and starts new one
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
console_newline:
|
||||||
|
push af
|
||||||
|
console_newline_:
|
||||||
|
call console_wait_vbl
|
||||||
|
call console_flush_
|
||||||
|
call console_scroll_up_
|
||||||
|
call console_flush_
|
||||||
|
jp console_apply_scroll_
|
||||||
|
|
||||||
|
|
||||||
|
console_scroll_up_:
|
||||||
|
push bc
|
||||||
|
push hl
|
||||||
|
|
||||||
|
; Scroll up 8 pixels
|
||||||
|
ld a,(console_scroll)
|
||||||
|
add 8
|
||||||
|
ld (console_scroll),a
|
||||||
|
|
||||||
|
; Start new clear line
|
||||||
|
ld a,' '
|
||||||
|
ld hl,console_buf + console_width - 1
|
||||||
|
ld b,console_width
|
||||||
|
- ldd (hl),a
|
||||||
|
dec b
|
||||||
|
jr nz,-
|
||||||
|
ld a,<(console_buf + console_width)
|
||||||
|
ld (console_pos),a
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop bc
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Displays current line's contents without scrolling.
|
||||||
|
; Preserved: A, BC, DE, HL
|
||||||
|
console_flush:
|
||||||
|
push af
|
||||||
|
call console_wait_vbl
|
||||||
|
call console_flush_
|
||||||
|
console_apply_scroll_:
|
||||||
|
ld a,(console_scroll)
|
||||||
|
sub 136
|
||||||
|
sta SCY
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
console_flush_:
|
||||||
|
push de
|
||||||
|
push hl
|
||||||
|
|
||||||
|
; Address of row in nametable
|
||||||
|
ld a,(console_scroll)
|
||||||
|
ld l,a
|
||||||
|
ld h,(>BGMAP0) >> 2
|
||||||
|
add hl,hl
|
||||||
|
add hl,hl
|
||||||
|
|
||||||
|
; Copy line
|
||||||
|
ld de,console_buf + console_width
|
||||||
|
- dec e
|
||||||
|
ld a,(de)
|
||||||
|
ldi (hl),a
|
||||||
|
ld a,e
|
||||||
|
cp <console_buf
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop de
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
ASCII:
|
||||||
|
.incbin "console.bin"
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
; CPU speed manipulation.
|
||||||
|
|
||||||
|
; Switches to normal speed. No effect on DMG.
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
cpu_norm:
|
||||||
|
; Do nothing if not CGB
|
||||||
|
ld a,(gb_id)
|
||||||
|
and gb_id_cgb
|
||||||
|
ret z
|
||||||
|
|
||||||
|
lda KEY1
|
||||||
|
rlca
|
||||||
|
ret nc
|
||||||
|
jr cpu_speed_toggle
|
||||||
|
|
||||||
|
|
||||||
|
; Switches to double speed. No effect on DMG.
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
cpu_fast:
|
||||||
|
; Do nothing if not CGB
|
||||||
|
ld a,(gb_id)
|
||||||
|
and gb_id_cgb
|
||||||
|
ret z
|
||||||
|
|
||||||
|
lda KEY1
|
||||||
|
rlca
|
||||||
|
ret c
|
||||||
|
cpu_speed_toggle:
|
||||||
|
di
|
||||||
|
lda IE
|
||||||
|
push af
|
||||||
|
xor a
|
||||||
|
sta IE
|
||||||
|
sta IF
|
||||||
|
wreg P1,$30
|
||||||
|
wreg KEY1,1
|
||||||
|
stop
|
||||||
|
nop
|
||||||
|
pop af
|
||||||
|
sta IE
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Determines current CPU speed without using KEY1.
|
||||||
|
; A=1 if fast, 0 if normal. Always 0 on DMG.
|
||||||
|
; Preserved: BC, DE,HL
|
||||||
|
get_cpu_speed:
|
||||||
|
push bc
|
||||||
|
call sync_apu
|
||||||
|
wreg NR14,$C0
|
||||||
|
wreg NR11,-1
|
||||||
|
wreg NR12,8
|
||||||
|
wreg NR14,$C0
|
||||||
|
ld bc,-$262
|
||||||
|
- inc bc
|
||||||
|
lda NR52
|
||||||
|
and 1
|
||||||
|
jr nz,-
|
||||||
|
ld a,0
|
||||||
|
bit 7,b
|
||||||
|
jr nz,+
|
||||||
|
inc a
|
||||||
|
+ pop bc
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
; CRC-32 checksum calculation
|
||||||
|
|
||||||
|
.define checksum dp+0 ; little-endian, complemented
|
||||||
|
.redefine dp dp+4
|
||||||
|
|
||||||
|
|
||||||
|
; Initializes checksum module. Might initialize tables
|
||||||
|
; in the future.
|
||||||
|
init_crc:
|
||||||
|
jr reset_crc
|
||||||
|
|
||||||
|
|
||||||
|
; Clears CRC
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
reset_crc:
|
||||||
|
ld a,$FF
|
||||||
|
sta checksum+0
|
||||||
|
sta checksum+1
|
||||||
|
sta checksum+2
|
||||||
|
sta checksum+3
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Updates current checksum with byte A
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
; Time: 237 cycles average
|
||||||
|
update_crc:
|
||||||
|
; 65 cycles + 8*cycles per bit
|
||||||
|
; min cycles per bit: 14
|
||||||
|
; max cycles per bit: 29
|
||||||
|
push af
|
||||||
|
push bc
|
||||||
|
push de
|
||||||
|
push hl
|
||||||
|
|
||||||
|
ld hl,checksum+3
|
||||||
|
ld b,(hl)
|
||||||
|
dec l
|
||||||
|
ld c,(hl)
|
||||||
|
dec l
|
||||||
|
ld d,(hl)
|
||||||
|
dec l
|
||||||
|
xor (hl)
|
||||||
|
|
||||||
|
ld h,8
|
||||||
|
- srl b
|
||||||
|
rr c
|
||||||
|
rr d
|
||||||
|
rra
|
||||||
|
jr nc,+
|
||||||
|
ld e,a
|
||||||
|
ld a,b
|
||||||
|
xor $ED
|
||||||
|
ld b,a
|
||||||
|
ld a,c
|
||||||
|
xor $B8
|
||||||
|
ld c,a
|
||||||
|
ld a,d
|
||||||
|
xor $83
|
||||||
|
ld d,a
|
||||||
|
ld a,e
|
||||||
|
xor $20
|
||||||
|
+ dec h
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
ld h,>checksum
|
||||||
|
ldi (hl),a
|
||||||
|
ld (hl),d
|
||||||
|
inc l
|
||||||
|
ld (hl),c
|
||||||
|
inc l
|
||||||
|
ld (hl),b
|
||||||
|
|
||||||
|
pop hl
|
||||||
|
pop de
|
||||||
|
pop bc
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
; Fast table-based CRC-32
|
||||||
|
|
||||||
|
.define crc_tables (bss+$FF)&$FF00 ; 256-byte aligned
|
||||||
|
.redefine bss crc_tables+$400
|
||||||
|
|
||||||
|
|
||||||
|
; Initializes fast CRC tables and resets checksum.
|
||||||
|
; Time: 47 msec
|
||||||
|
init_crc_fast:
|
||||||
|
ld l,0
|
||||||
|
@next:
|
||||||
|
xor a
|
||||||
|
ld c,a
|
||||||
|
ld d,a
|
||||||
|
ld e,l
|
||||||
|
|
||||||
|
ld h,8
|
||||||
|
- rra
|
||||||
|
rr c
|
||||||
|
rr d
|
||||||
|
rr e
|
||||||
|
jr nc,+
|
||||||
|
xor $ED
|
||||||
|
ld b,a
|
||||||
|
ld a,c
|
||||||
|
xor $B8
|
||||||
|
ld c,a
|
||||||
|
ld a,d
|
||||||
|
xor $83
|
||||||
|
ld d,a
|
||||||
|
ld a,e
|
||||||
|
xor $20
|
||||||
|
ld e,a
|
||||||
|
ld a,b
|
||||||
|
|
||||||
|
+ dec h
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
ld h,>crc_tables
|
||||||
|
ld (hl),e
|
||||||
|
inc h
|
||||||
|
ld (hl),d
|
||||||
|
inc h
|
||||||
|
ld (hl),c
|
||||||
|
inc h
|
||||||
|
ld (hl),a
|
||||||
|
|
||||||
|
inc l
|
||||||
|
jr nz,@next
|
||||||
|
|
||||||
|
jp init_crc
|
||||||
|
|
||||||
|
|
||||||
|
; Faster version of update_crc
|
||||||
|
; Preserved: BC, DE
|
||||||
|
; Time: 50 cycles (including CALL)
|
||||||
|
update_crc_fast:
|
||||||
|
|
||||||
|
; Fastest inline macro version of update_crc_fast
|
||||||
|
; Time: 40 cycles
|
||||||
|
; Size: 28 bytes
|
||||||
|
.macro update_crc_fast
|
||||||
|
ld l,a ; 1
|
||||||
|
lda checksum ; 3
|
||||||
|
xor l ; 1
|
||||||
|
ld l,a ; 1
|
||||||
|
ld h,>crc_tables ; 2
|
||||||
|
|
||||||
|
lda checksum+1 ; 3
|
||||||
|
xor (hl) ; 2
|
||||||
|
inc h ; 1
|
||||||
|
sta checksum ; 3
|
||||||
|
|
||||||
|
lda checksum+2 ; 3
|
||||||
|
xor (hl) ; 2
|
||||||
|
inc h ; 1
|
||||||
|
sta checksum+1 ; 3
|
||||||
|
|
||||||
|
lda checksum+3 ; 3
|
||||||
|
xor (hl) ; 2
|
||||||
|
inc h ; 1
|
||||||
|
sta checksum+2 ; 3
|
||||||
|
|
||||||
|
ld a,(hl) ; 2
|
||||||
|
sta checksum+3 ; 3
|
||||||
|
.endm
|
||||||
|
update_crc_fast
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,220 @@
|
||||||
|
; Delays in cycles, milliseconds, etc.
|
||||||
|
|
||||||
|
; All routines are re-entrant (no global data). Routines never
|
||||||
|
; touch BC, DE, or HL registers. These ASSUME CPU is at normal
|
||||||
|
; speed. If running at double speed, msec/usec delays are half advertised.
|
||||||
|
|
||||||
|
; Delays n cycles, from 0 to 16777215
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro delay ARGS n
|
||||||
|
.if n < 0
|
||||||
|
.printt "Delay must be >= 0"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
.if n > 16777215
|
||||||
|
.printt "Delay must be < 16777216"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
delay_ n&$FFFF, n>>16
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Delays n clocks, from 0 to 16777216*4. Must be multiple of 4.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro delay_clocks ARGS n
|
||||||
|
.if n # 4 != 0
|
||||||
|
.printt "Delay must be a multiple of 4"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
delay_ (n/4)&$FFFF,(n/4)>>16
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Delays n microseconds (1/1000000 second)
|
||||||
|
; n can range from 0 to 4000 usec.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro delay_usec ARGS n
|
||||||
|
.if n < 0
|
||||||
|
.printt "Delay must be >= 0"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
.if n > 4000
|
||||||
|
.printt "Delay must be <= 4000 usec"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
delay_ ((n * 1048576 + 500000) / 1000000)&$FFFF,((n * 1048576 + 500000) / 1000000)>>16
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Delays n milliseconds (1/1000 second)
|
||||||
|
; n can range from 0 to 10000 msec.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro delay_msec ARGS n
|
||||||
|
.if n < 0
|
||||||
|
.printt "Delay must be >= 0"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
.if n > 10000
|
||||||
|
.printt "Delay must be <= 10000 msec"
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
delay_ ((n * 1048576 + 500) / 1000)&$FFFF, ((n * 1048576 + 500) / 1000)>>16
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; All the low/high quantities are to deal wla-dx's asinine
|
||||||
|
; restriction full expressions must evaluate to a 16-bit
|
||||||
|
; value. If the author ever rectifies this, all "high"
|
||||||
|
; arguments can be treated as zero and removed. Better yet,
|
||||||
|
; I'll just find an assembler that didn't crawl out of
|
||||||
|
; the sewer (this is one of too many bugs I've wasted
|
||||||
|
; hours working around).
|
||||||
|
|
||||||
|
.define max_short_delay 28
|
||||||
|
|
||||||
|
.macro delay_long_ ARGS n, high
|
||||||
|
; 0+ to avoid assembler treating as memory read
|
||||||
|
ld a,0+(((high<<16)+n) - 11) >> 16
|
||||||
|
call delay_65536a_9_cycles_
|
||||||
|
delay_nosave_ (((high<<16)+n) - 11)&$FFFF, 0
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Doesn't save AF, allowing minimization of AF save/restore
|
||||||
|
.macro delay_nosave_ ARGS n, high
|
||||||
|
; 65536+11 = maximum delay using delay_256a_9_cycles_
|
||||||
|
; 255+22 = maximum delay using delay_a_20_cycles
|
||||||
|
; 22 = minimum delay using delay_a_20_cycles
|
||||||
|
.if high > 1
|
||||||
|
delay_long_ n, high
|
||||||
|
.else
|
||||||
|
.if high*n > 11
|
||||||
|
delay_long_ n, high
|
||||||
|
.else
|
||||||
|
.if (high*(255+22+1))|n > 255+22
|
||||||
|
ld a,>(((high<<16)+n) - 11)
|
||||||
|
call delay_256a_9_cycles_
|
||||||
|
delay_nosave_ <(((high<<16)+n) - 11), 0
|
||||||
|
.else
|
||||||
|
.if n >= 22
|
||||||
|
ld a,n - 22
|
||||||
|
call delay_a_20_cycles
|
||||||
|
.else
|
||||||
|
delay_short_ n
|
||||||
|
.endif
|
||||||
|
.endif
|
||||||
|
.endif
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro delay_ ARGS low, high
|
||||||
|
.if (high*(max_short_delay+1))|low > max_short_delay
|
||||||
|
push af
|
||||||
|
delay_nosave_ ((high<<16)+low - 7)&$FFFF, ((high<<16)+low - 7)>>16
|
||||||
|
pop af
|
||||||
|
.else
|
||||||
|
delay_short_ low
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
|
||||||
|
; Delays A cycles + overhead
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
; Time: A+20 cycles (including CALL)
|
||||||
|
delay_a_20_cycles:
|
||||||
|
- sub 5 ; 2
|
||||||
|
jr nc,- ;3/2 do multiples of 5
|
||||||
|
rra ; 1
|
||||||
|
jr nc,+ ;3/2 bit 0
|
||||||
|
+ adc 1 ; 2
|
||||||
|
ret nc ;5/2 -1: 0 cycles
|
||||||
|
ret z ;5/2 0: 2 cycles
|
||||||
|
nop ; 1 1: 4 cycles
|
||||||
|
ret ; 4 (thanks to dclxvi for original algorithm)
|
||||||
|
|
||||||
|
; Delays A*256 cycles + overhead
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
; Time: A*256+12 cycles (including CALL)
|
||||||
|
delay_256a_12_cycles:
|
||||||
|
or a ; 1
|
||||||
|
ret z ; 5/2
|
||||||
|
delay_256a_9_cycles_:
|
||||||
|
- delay 256-4
|
||||||
|
dec a ; 1
|
||||||
|
jr nz,- ;3/2
|
||||||
|
ret ; 4
|
||||||
|
|
||||||
|
; Delays A*65536 cycles + overhead
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
; Time: A*65536+12 cycles (including CALL)
|
||||||
|
delay_65536a_12_cycles:
|
||||||
|
or a ; 1
|
||||||
|
ret z ;5/2
|
||||||
|
delay_65536a_9_cycles_:
|
||||||
|
- delay 65536-4
|
||||||
|
dec a ; 1
|
||||||
|
jr nz,- ;3/2
|
||||||
|
ret ; 4
|
||||||
|
|
||||||
|
; Delays H*256+L cycles + overhead
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
; Time: H*256+L+51 cycles
|
||||||
|
delay_hl_51_cycles:
|
||||||
|
push af
|
||||||
|
ld a,h
|
||||||
|
call delay_256a_12_cycles
|
||||||
|
ld a,l
|
||||||
|
call delay_a_20_cycles
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
; delay_short_ macro calls into these
|
||||||
|
.ds max_short_delay-10,$00 ; NOP repeated several times
|
||||||
|
delay_unrolled_:
|
||||||
|
ret
|
||||||
|
|
||||||
|
.macro delay_short_ ARGS n
|
||||||
|
.if n < 0
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
.if n > max_short_delay
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.if n == 1
|
||||||
|
nop
|
||||||
|
.endif
|
||||||
|
.if n == 2
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
.endif
|
||||||
|
.if n == 3
|
||||||
|
.byte $18,$00 ; JR +0
|
||||||
|
.endif
|
||||||
|
.if n == 4
|
||||||
|
.byte $18,$00 ; JR +0
|
||||||
|
nop
|
||||||
|
.endif
|
||||||
|
.if n == 5
|
||||||
|
.byte $18,$00 ; JR +0
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
.endif
|
||||||
|
.if n == 6
|
||||||
|
.byte $18,$00 ; JR +0
|
||||||
|
.byte $18,$00 ; JR +0
|
||||||
|
.endif
|
||||||
|
.if n == 7
|
||||||
|
push af
|
||||||
|
pop af
|
||||||
|
.endif
|
||||||
|
.if n == 8
|
||||||
|
push af
|
||||||
|
pop af
|
||||||
|
nop
|
||||||
|
.endif
|
||||||
|
.if n == 9
|
||||||
|
push af
|
||||||
|
pop af
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
.endif
|
||||||
|
.if n >= 10
|
||||||
|
call delay_unrolled_ + 10 - n
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
; Game Boy hardware addresses
|
||||||
|
|
||||||
|
; Memory
|
||||||
|
.define VRAM $8000 ; video memory
|
||||||
|
.define TILES $8000 ; tile images
|
||||||
|
.define BGMAP0 $9800 ; first 32x32 tilemap
|
||||||
|
.define BGMAP1 $9C00 ; second 32x32 tilemap
|
||||||
|
.define WRAM $C000 ; internal memory
|
||||||
|
.define OAM $FE00 ; sprite memory
|
||||||
|
.define HRAM $FF80 ; fast memory for LDH
|
||||||
|
|
||||||
|
.define P1 $FF00
|
||||||
|
|
||||||
|
; Game link I/O
|
||||||
|
.define SB $FF01
|
||||||
|
.define SC $FF02
|
||||||
|
|
||||||
|
; Interrupts
|
||||||
|
.define DIV $FF04
|
||||||
|
.define TIMA $FF05
|
||||||
|
.define TMA $FF06
|
||||||
|
.define TAC $FF07
|
||||||
|
.define IF $FF0F
|
||||||
|
.define IE $FFFF
|
||||||
|
|
||||||
|
; LCD registers
|
||||||
|
.define LCDC $FF40 ; control
|
||||||
|
.define STAT $FF41 ; status
|
||||||
|
.define SCY $FF42 ; scroll Y
|
||||||
|
.define SCX $FF43 ; scroll X
|
||||||
|
.define LY $FF44 ; current Y being rendered
|
||||||
|
.define BGP $FF47
|
||||||
|
|
||||||
|
.define KEY1 $FF4D ; for changing CPU speed
|
||||||
|
.define VBK $FF4F
|
||||||
|
|
||||||
|
; Sound registers
|
||||||
|
.define NR10 $FF10
|
||||||
|
.define NR11 $FF11
|
||||||
|
.define NR12 $FF12
|
||||||
|
.define NR13 $FF13
|
||||||
|
.define NR14 $FF14
|
||||||
|
|
||||||
|
.define NR21 $FF16
|
||||||
|
.define NR22 $FF17
|
||||||
|
.define NR23 $FF18
|
||||||
|
.define NR24 $FF19
|
||||||
|
|
||||||
|
.define NR30 $FF1A
|
||||||
|
.define NR31 $FF1B
|
||||||
|
.define NR32 $FF1C
|
||||||
|
.define NR33 $FF1D
|
||||||
|
.define NR34 $FF1E
|
||||||
|
|
||||||
|
.define NR41 $FF20
|
||||||
|
.define NR42 $FF21
|
||||||
|
.define NR43 $FF22
|
||||||
|
.define NR44 $FF23
|
||||||
|
|
||||||
|
.define NR50 $FF24
|
||||||
|
.define NR51 $FF25
|
||||||
|
.define NR52 $FF26
|
||||||
|
|
||||||
|
.define WAVE $FF30
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
; Framework for CPU instruction tests
|
||||||
|
|
||||||
|
; Calls test_instr with each instruction copied
|
||||||
|
; to instr, with a JP instr_done after it.
|
||||||
|
; Verifies checksum after testing instruction and
|
||||||
|
; prints opcode if it's wrong.
|
||||||
|
|
||||||
|
.include "checksums.s"
|
||||||
|
.include "cpu_speed.s"
|
||||||
|
.include "apu.s"
|
||||||
|
.include "crc_fast.s"
|
||||||
|
|
||||||
|
.define instr $DEF8
|
||||||
|
.define rp_temp (instr-4)
|
||||||
|
|
||||||
|
.define temp bss
|
||||||
|
|
||||||
|
; Sets SP to word at addr
|
||||||
|
; Preserved: BC, DE
|
||||||
|
.macro ldsp ; addr
|
||||||
|
ld a,(\1)
|
||||||
|
ld l,a
|
||||||
|
ld a,((\1)+1)
|
||||||
|
ld h,a
|
||||||
|
ld sp,hl
|
||||||
|
.endm
|
||||||
|
|
||||||
|
main:
|
||||||
|
call cpu_fast
|
||||||
|
call init_crc_fast
|
||||||
|
call checksums_init
|
||||||
|
set_test 0
|
||||||
|
|
||||||
|
ld hl,instrs
|
||||||
|
- ; Copy instruction
|
||||||
|
ld a,(hl+)
|
||||||
|
ld (instr),a
|
||||||
|
ld a,(hl+)
|
||||||
|
ld (instr+1),a
|
||||||
|
ld a,(hl+)
|
||||||
|
ld (instr+2),a
|
||||||
|
push hl
|
||||||
|
|
||||||
|
; Put JP instr_done after it
|
||||||
|
ld a,$C3
|
||||||
|
ld (instr+3),a
|
||||||
|
ld a,<instr_done
|
||||||
|
ld (instr+4),a
|
||||||
|
ld a,>instr_done
|
||||||
|
ld (instr+5),a
|
||||||
|
|
||||||
|
call reset_crc
|
||||||
|
call test_instr
|
||||||
|
|
||||||
|
call checksums_compare
|
||||||
|
jr z,passed
|
||||||
|
|
||||||
|
set_test 1
|
||||||
|
ld a,(instr)
|
||||||
|
call print_a
|
||||||
|
cp $CB
|
||||||
|
jr nz,+
|
||||||
|
ld a,(instr+1)
|
||||||
|
call print_a
|
||||||
|
+
|
||||||
|
|
||||||
|
passed:
|
||||||
|
; Next instruction
|
||||||
|
pop hl
|
||||||
|
ld a,l
|
||||||
|
cp <instrs_end
|
||||||
|
jr nz,-
|
||||||
|
ld a,h
|
||||||
|
cp >instrs_end
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
jp tests_done
|
||||||
|
|
||||||
|
|
||||||
|
; Updates checksum with AF, BC, DE, and HL
|
||||||
|
checksum_af_bc_de_hl:
|
||||||
|
push hl
|
||||||
|
|
||||||
|
push af
|
||||||
|
update_crc_fast
|
||||||
|
pop hl
|
||||||
|
ld a,l
|
||||||
|
update_crc_fast
|
||||||
|
|
||||||
|
ld a,b
|
||||||
|
update_crc_fast
|
||||||
|
ld a,c
|
||||||
|
update_crc_fast
|
||||||
|
|
||||||
|
ld a,d
|
||||||
|
update_crc_fast
|
||||||
|
ld a,e
|
||||||
|
update_crc_fast
|
||||||
|
|
||||||
|
pop de
|
||||||
|
ld a,d
|
||||||
|
update_crc_fast
|
||||||
|
ld a,e
|
||||||
|
update_crc_fast
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
; General macros
|
||||||
|
|
||||||
|
; Reads A from addr, from $FF00 to $FFFF
|
||||||
|
; Preserved: F, BC, DE, HL
|
||||||
|
; Time: 3 cycles
|
||||||
|
.macro lda ARGS addr
|
||||||
|
ldh a,(addr - $FF00)
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Writes A to addr, from $FF00 to $FFFF
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
; Time: 3 cycles
|
||||||
|
.macro sta ARGS addr
|
||||||
|
ldh (addr - $FF00),a
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Writes immediate data to addr, from $FF00 to $FFFF
|
||||||
|
; Preserved: F, BC, DE, HL
|
||||||
|
; Time: 5 cycles
|
||||||
|
.macro wreg ARGS addr, data
|
||||||
|
ld a,data
|
||||||
|
sta addr
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Calls routine multiple times, with A having the
|
||||||
|
; value 'start' the first time, 'start+step' the
|
||||||
|
; second time, up to 'end' for the last time.
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
.macro for_loop ; routine,start,end,step
|
||||||
|
ld a,\2
|
||||||
|
|
||||||
|
for_loop\@:
|
||||||
|
push af
|
||||||
|
call \1
|
||||||
|
pop af
|
||||||
|
|
||||||
|
add \4
|
||||||
|
cp <(\3 + \4)
|
||||||
|
jr nz,for_loop\@
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Calls routine n times. The value of A in the routine
|
||||||
|
; counts from 0 to n-1.
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
.macro loop_n_times ; routine,n
|
||||||
|
for_loop \1,0,\2 - 1,+1
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; Same as for_loop, but counts with 16-bit value in BC.
|
||||||
|
; Preserved: DE, HL
|
||||||
|
.macro for_loop16 ; routine,start,end,step
|
||||||
|
ld bc,\2
|
||||||
|
|
||||||
|
for_loop16\@:
|
||||||
|
push bc
|
||||||
|
call \1
|
||||||
|
pop bc
|
||||||
|
|
||||||
|
ld a,c
|
||||||
|
add <\4
|
||||||
|
ld c,a
|
||||||
|
|
||||||
|
ld a,b
|
||||||
|
adc >\4
|
||||||
|
ld b,a
|
||||||
|
|
||||||
|
cp >(\3+\4)
|
||||||
|
jr nz,for_loop16\@
|
||||||
|
|
||||||
|
ld a,c
|
||||||
|
cp <(\3+\4)
|
||||||
|
jr nz,for_loop16\@
|
||||||
|
.endm
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
; RST handlers
|
||||||
|
.bank 0 slot 0
|
||||||
|
.org 0
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
.ds 6,0
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
.ds 6,0
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
.ds 6,0
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
.ds 6,0
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
.ds 6,0
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
.ds 6,0
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
.ds 6,0
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
.ds 6,0
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
.ds 6,0
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
.ds 6,0
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
.ds 6,0
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
; Printing of numeric values
|
||||||
|
|
||||||
|
; Prints value of indicated register/pair
|
||||||
|
; as 2/4 hex digits, followed by a space.
|
||||||
|
; Updates checksum with printed values.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
|
||||||
|
print_regs:
|
||||||
|
call print_af
|
||||||
|
call print_bc
|
||||||
|
call print_de
|
||||||
|
call print_hl
|
||||||
|
call print_newline
|
||||||
|
ret
|
||||||
|
|
||||||
|
print_a:
|
||||||
|
push af
|
||||||
|
print_a_:
|
||||||
|
call print_hex
|
||||||
|
ld a,' '
|
||||||
|
call print_char_nocrc
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
print_af:
|
||||||
|
push af
|
||||||
|
call print_hex
|
||||||
|
pop af
|
||||||
|
print_f:
|
||||||
|
push bc
|
||||||
|
push af
|
||||||
|
pop bc
|
||||||
|
call print_c
|
||||||
|
pop bc
|
||||||
|
ret
|
||||||
|
|
||||||
|
print_b:
|
||||||
|
push af
|
||||||
|
ld a,b
|
||||||
|
jr print_a_
|
||||||
|
|
||||||
|
print_c:
|
||||||
|
push af
|
||||||
|
ld a,c
|
||||||
|
jr print_a_
|
||||||
|
|
||||||
|
print_d:
|
||||||
|
push af
|
||||||
|
ld a,d
|
||||||
|
jr print_a_
|
||||||
|
|
||||||
|
print_e:
|
||||||
|
push af
|
||||||
|
ld a,e
|
||||||
|
jr print_a_
|
||||||
|
|
||||||
|
print_h:
|
||||||
|
push af
|
||||||
|
ld a,h
|
||||||
|
jr print_a_
|
||||||
|
|
||||||
|
print_l:
|
||||||
|
push af
|
||||||
|
ld a,l
|
||||||
|
jr print_a_
|
||||||
|
|
||||||
|
print_bc:
|
||||||
|
push af
|
||||||
|
push bc
|
||||||
|
print_bc_:
|
||||||
|
ld a,b
|
||||||
|
call print_hex
|
||||||
|
ld a,c
|
||||||
|
pop bc
|
||||||
|
jr print_a_
|
||||||
|
|
||||||
|
print_de:
|
||||||
|
push af
|
||||||
|
push bc
|
||||||
|
ld b,d
|
||||||
|
ld c,e
|
||||||
|
jr print_bc_
|
||||||
|
|
||||||
|
print_hl:
|
||||||
|
push af
|
||||||
|
push bc
|
||||||
|
ld b,h
|
||||||
|
ld c,l
|
||||||
|
jr print_bc_
|
||||||
|
|
||||||
|
|
||||||
|
; Prints A as two hex chars and updates checksum
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
print_hex:
|
||||||
|
call update_crc
|
||||||
|
print_hex_nocrc:
|
||||||
|
push af
|
||||||
|
swap a
|
||||||
|
call +
|
||||||
|
pop af
|
||||||
|
|
||||||
|
+ and $0F
|
||||||
|
cp 10
|
||||||
|
jr c,+
|
||||||
|
add 7
|
||||||
|
+ add '0'
|
||||||
|
jp print_char_nocrc
|
||||||
|
|
||||||
|
|
||||||
|
; Prints char_nz if Z flag is clear,
|
||||||
|
; char_z if Z flag is set.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro print_nz ARGS char_nz, char_z
|
||||||
|
push af
|
||||||
|
ld a,char_nz
|
||||||
|
jr nz,print_nz\@
|
||||||
|
ld a,char_z
|
||||||
|
print_nz\@:
|
||||||
|
call print_char
|
||||||
|
pop af
|
||||||
|
.endm
|
||||||
|
|
||||||
|
|
||||||
|
; Prints char_nc if C flag is clear,
|
||||||
|
; char_c if C flag is set.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro print_nc ARGS char_nc, char_c
|
||||||
|
push af
|
||||||
|
ld a,char_nc
|
||||||
|
jr nz,print_nc\@
|
||||||
|
ld a,char_c
|
||||||
|
print_nc\@:
|
||||||
|
call print_char
|
||||||
|
pop af
|
||||||
|
.endm
|
||||||
|
|
||||||
|
|
||||||
|
; Prints A as 2 decimal digits
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
print_dec2:
|
||||||
|
push af
|
||||||
|
push bc
|
||||||
|
jr +
|
||||||
|
|
||||||
|
|
||||||
|
; Prints A as 1-3 digit decimal value
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
print_dec:
|
||||||
|
push af
|
||||||
|
push bc
|
||||||
|
|
||||||
|
cp 10
|
||||||
|
jr c,++
|
||||||
|
ld c,100
|
||||||
|
cp c
|
||||||
|
call nc,@digit
|
||||||
|
+ ld c,10
|
||||||
|
call @digit
|
||||||
|
++ add '0'
|
||||||
|
call print_char
|
||||||
|
|
||||||
|
pop bc
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
@digit:
|
||||||
|
ld b,'0'-1
|
||||||
|
- inc b
|
||||||
|
sub c
|
||||||
|
jr nc,-
|
||||||
|
add c
|
||||||
|
|
||||||
|
ld c,a
|
||||||
|
ld a,b
|
||||||
|
call print_char
|
||||||
|
ld a,c
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
; Main printing routine that checksums and
|
||||||
|
; prints to output device
|
||||||
|
|
||||||
|
; Character that does equivalent of print_newline
|
||||||
|
.define newline 10
|
||||||
|
|
||||||
|
; Prints char without updating checksum
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
.define print_char_nocrc bss
|
||||||
|
.redefine bss bss+3
|
||||||
|
|
||||||
|
|
||||||
|
; Initializes printing. HL = print routine
|
||||||
|
init_printing:
|
||||||
|
ld a,l
|
||||||
|
ld (print_char_nocrc+1),a
|
||||||
|
ld a,h
|
||||||
|
ld (print_char_nocrc+2),a
|
||||||
|
jr show_printing
|
||||||
|
|
||||||
|
|
||||||
|
; Hides/shows further printing
|
||||||
|
; Preserved: BC, DE, HL
|
||||||
|
hide_printing:
|
||||||
|
ld a,$C9 ; RET
|
||||||
|
jr +
|
||||||
|
show_printing:
|
||||||
|
ld a,$C3 ; JP (nn)
|
||||||
|
+ ld (print_char_nocrc),a
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Prints character and updates checksum UNLESS
|
||||||
|
; it's a newline.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
print_char:
|
||||||
|
push af
|
||||||
|
cp newline
|
||||||
|
call nz,update_crc
|
||||||
|
call print_char_nocrc
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Prints space. Does NOT update checksum.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
print_space:
|
||||||
|
push af
|
||||||
|
ld a,' '
|
||||||
|
call print_char_nocrc
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Advances to next line. Does NOT update checksum.
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
print_newline:
|
||||||
|
push af
|
||||||
|
ld a,newline
|
||||||
|
call print_char_nocrc
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Prints immediate string
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro print_str ; string,string2
|
||||||
|
push hl
|
||||||
|
call print_str_
|
||||||
|
.byte \1
|
||||||
|
.if NARGS > 1
|
||||||
|
.byte \2
|
||||||
|
.endif
|
||||||
|
.if NARGS > 2
|
||||||
|
.byte \3
|
||||||
|
.endif
|
||||||
|
.byte 0
|
||||||
|
pop hl
|
||||||
|
.endm
|
||||||
|
|
||||||
|
print_str_:
|
||||||
|
pop hl
|
||||||
|
call print_str_hl
|
||||||
|
jp hl
|
||||||
|
|
||||||
|
|
||||||
|
; Prints zero-terminated string pointed to by HL.
|
||||||
|
; On return, HL points to byte AFTER zero terminator.
|
||||||
|
; Preserved: AF, BC, DE
|
||||||
|
print_str_hl:
|
||||||
|
push af
|
||||||
|
jr +
|
||||||
|
- call print_char
|
||||||
|
+ ldi a,(hl)
|
||||||
|
or a
|
||||||
|
jr nz,-
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,142 @@
|
||||||
|
; Common routines and runtime
|
||||||
|
|
||||||
|
; Must be defined by target-specific runtime:
|
||||||
|
;
|
||||||
|
; init_runtime: ; target-specific inits
|
||||||
|
; std_print: ; default routine to print char A
|
||||||
|
; post_exit: ; called at end of std_exit
|
||||||
|
; report_byte: ; report A to user
|
||||||
|
|
||||||
|
.define RUNTIME_INCLUDED 1
|
||||||
|
|
||||||
|
.ifndef bss
|
||||||
|
; address of next normal variable
|
||||||
|
.define bss $D800
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.ifndef dp
|
||||||
|
; address of next direct-page ($FFxx) variable
|
||||||
|
.define dp $FF80
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; DMG/CGB hardware identifier
|
||||||
|
.define gb_id_cgb $10 ; mask for testing CGB bit
|
||||||
|
.define gb_id_devcart $04 ; mask for testing "on devcart" bit
|
||||||
|
|
||||||
|
.define gb_id bss
|
||||||
|
.redefine bss bss+1
|
||||||
|
|
||||||
|
; Stack is normally here
|
||||||
|
.define std_stack $DFFF
|
||||||
|
|
||||||
|
; Copies $1000 bytes from HL to $C000, then jumps to it.
|
||||||
|
; A is preserved for jumped-to code.
|
||||||
|
copy_to_wram_then_run:
|
||||||
|
ld b,a
|
||||||
|
|
||||||
|
ld de,$C000
|
||||||
|
ld c,$10
|
||||||
|
- ldi a,(hl)
|
||||||
|
ld (de),a
|
||||||
|
inc e
|
||||||
|
jr nz,-
|
||||||
|
inc d
|
||||||
|
dec c
|
||||||
|
jr nz,-
|
||||||
|
|
||||||
|
ld a,b
|
||||||
|
jp $C000
|
||||||
|
|
||||||
|
.ifndef CUSTOM_RESET
|
||||||
|
reset:
|
||||||
|
; Run code from $C000, as is done on devcart. This
|
||||||
|
; ensures minimal difference in how it behaves.
|
||||||
|
ld hl,$4000
|
||||||
|
jp copy_to_wram_then_run
|
||||||
|
|
||||||
|
.bank 1 slot 1
|
||||||
|
.org $0 ; otherwise wla pads with lots of zeroes
|
||||||
|
jp std_reset
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; Common routines
|
||||||
|
.include "gb.inc"
|
||||||
|
.include "macros.inc"
|
||||||
|
.include "delay.s"
|
||||||
|
.include "crc.s"
|
||||||
|
.include "printing.s"
|
||||||
|
.include "numbers.s"
|
||||||
|
.include "testing.s"
|
||||||
|
|
||||||
|
; Sets up hardware and runs main
|
||||||
|
std_reset:
|
||||||
|
|
||||||
|
; Init hardware
|
||||||
|
di
|
||||||
|
ld sp,std_stack
|
||||||
|
|
||||||
|
; Save DMG/CGB id
|
||||||
|
ld (gb_id),a
|
||||||
|
|
||||||
|
; Init hardware
|
||||||
|
.ifndef BUILD_GBS
|
||||||
|
wreg TAC,$00
|
||||||
|
wreg IF,$00
|
||||||
|
wreg IE,$00
|
||||||
|
.endif
|
||||||
|
|
||||||
|
wreg NR52,0 ; sound off
|
||||||
|
wreg NR52,$80 ; sound on
|
||||||
|
wreg NR51,$FF ; mono
|
||||||
|
wreg NR50,$77 ; volume
|
||||||
|
|
||||||
|
; TODO: clear all memory?
|
||||||
|
|
||||||
|
ld hl,std_print
|
||||||
|
call init_printing
|
||||||
|
call init_testing
|
||||||
|
call init_runtime
|
||||||
|
call reset_crc ; in case init_runtime prints anything
|
||||||
|
|
||||||
|
delay_msec 250
|
||||||
|
|
||||||
|
; Run user code
|
||||||
|
call main
|
||||||
|
|
||||||
|
; Default is to successful exit
|
||||||
|
ld a,0
|
||||||
|
jp exit
|
||||||
|
|
||||||
|
|
||||||
|
; Exits code and reports value of A
|
||||||
|
exit:
|
||||||
|
ld sp,std_stack
|
||||||
|
push af
|
||||||
|
call +
|
||||||
|
pop af
|
||||||
|
jp post_exit
|
||||||
|
|
||||||
|
+ push af
|
||||||
|
call print_newline
|
||||||
|
call show_printing
|
||||||
|
pop af
|
||||||
|
|
||||||
|
; Report exit status
|
||||||
|
cp 1
|
||||||
|
|
||||||
|
; 0: ""
|
||||||
|
ret c
|
||||||
|
|
||||||
|
; 1: "Failed"
|
||||||
|
jr nz,+
|
||||||
|
print_str "Failed",newline
|
||||||
|
ret
|
||||||
|
|
||||||
|
; n: "Failed #n"
|
||||||
|
+ print_str "Failed #"
|
||||||
|
call print_dec
|
||||||
|
call print_newline
|
||||||
|
ret
|
||||||
|
|
||||||
|
; returnOrg puts this code AFTER user code.
|
||||||
|
.section "runtime" returnOrg
|
||||||
|
|
@ -0,0 +1,176 @@
|
||||||
|
; Diagnostic and testing utilities
|
||||||
|
|
||||||
|
.define result bss+0
|
||||||
|
.define test_name bss+1
|
||||||
|
.redefine bss bss+3
|
||||||
|
|
||||||
|
|
||||||
|
; Sets test code and optional error text
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
.macro set_test ; code[,text[,text2]]
|
||||||
|
push hl
|
||||||
|
call set_test_
|
||||||
|
jr @set_test\@
|
||||||
|
.byte \1
|
||||||
|
.if NARGS > 1
|
||||||
|
.byte \2
|
||||||
|
.endif
|
||||||
|
.if NARGS > 2
|
||||||
|
.byte \3
|
||||||
|
.endif
|
||||||
|
.byte 0
|
||||||
|
@set_test\@:
|
||||||
|
pop hl
|
||||||
|
.endm
|
||||||
|
|
||||||
|
set_test_:
|
||||||
|
pop hl
|
||||||
|
push hl
|
||||||
|
push af
|
||||||
|
inc hl
|
||||||
|
inc hl
|
||||||
|
ldi a,(hl)
|
||||||
|
ld (result),a
|
||||||
|
ld a,l
|
||||||
|
ld (test_name),a
|
||||||
|
ld a,h
|
||||||
|
ld (test_name+1),a
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Initializes testing module
|
||||||
|
init_testing:
|
||||||
|
set_test $FF
|
||||||
|
call init_crc
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; Reports "Passed", then exits with code 0
|
||||||
|
tests_passed:
|
||||||
|
call print_newline
|
||||||
|
print_str "Passed"
|
||||||
|
ld a,0
|
||||||
|
jp exit
|
||||||
|
|
||||||
|
|
||||||
|
; Reports "Done" if set_test has never been used,
|
||||||
|
; "Passed" if set_test 0 was last used, or
|
||||||
|
; failure if set_test n was last used.
|
||||||
|
tests_done:
|
||||||
|
ld a,(result)
|
||||||
|
inc a
|
||||||
|
jr z,+
|
||||||
|
dec a
|
||||||
|
jr z,tests_passed
|
||||||
|
jr test_failed
|
||||||
|
+ print_str "Done"
|
||||||
|
ld a,0
|
||||||
|
jp exit
|
||||||
|
|
||||||
|
|
||||||
|
; Reports current error text and exits with result code
|
||||||
|
test_failed:
|
||||||
|
ld a,(test_name)
|
||||||
|
ld l,a
|
||||||
|
ld a,(test_name+1)
|
||||||
|
ld h,a
|
||||||
|
ld a,(hl)
|
||||||
|
or a
|
||||||
|
jr z,+
|
||||||
|
call print_newline
|
||||||
|
call print_str_hl
|
||||||
|
call print_newline
|
||||||
|
+
|
||||||
|
ld a,(result)
|
||||||
|
cp 1 ; if a = 0 then a = 1
|
||||||
|
adc 0
|
||||||
|
jp exit
|
||||||
|
|
||||||
|
|
||||||
|
; Prints checksum as 8-character hex value
|
||||||
|
; Preserved: AF, BC, DE, HL
|
||||||
|
print_crc:
|
||||||
|
push af
|
||||||
|
|
||||||
|
; Must read checksum entirely before printing,
|
||||||
|
; since printing updates it.
|
||||||
|
lda checksum
|
||||||
|
cpl
|
||||||
|
push af
|
||||||
|
|
||||||
|
lda checksum+1
|
||||||
|
cpl
|
||||||
|
push af
|
||||||
|
|
||||||
|
lda checksum+2
|
||||||
|
cpl
|
||||||
|
push af
|
||||||
|
|
||||||
|
lda checksum+3
|
||||||
|
cpl
|
||||||
|
|
||||||
|
call print_hex
|
||||||
|
pop af
|
||||||
|
call print_hex
|
||||||
|
pop af
|
||||||
|
call print_hex
|
||||||
|
pop af
|
||||||
|
call print_a
|
||||||
|
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; If checksum doesn't match expected, reports failed test.
|
||||||
|
; Passing 0 just prints checksum. Clears checksum afterwards.
|
||||||
|
.macro check_crc ARGS crc
|
||||||
|
.if crc == 0
|
||||||
|
call show_printing
|
||||||
|
call print_newline
|
||||||
|
call print_crc
|
||||||
|
.else
|
||||||
|
ld bc,(crc >> 16) ~ $FFFF
|
||||||
|
ld de,(crc & $FFFF) ~ $FFFF
|
||||||
|
call check_crc_
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
check_crc_:
|
||||||
|
lda checksum+0
|
||||||
|
cp e
|
||||||
|
jr nz,+
|
||||||
|
|
||||||
|
lda checksum+1
|
||||||
|
cp d
|
||||||
|
jr nz,+
|
||||||
|
|
||||||
|
lda checksum+2
|
||||||
|
cp c
|
||||||
|
jr nz,+
|
||||||
|
|
||||||
|
lda checksum+3
|
||||||
|
cp b
|
||||||
|
jr nz,+
|
||||||
|
|
||||||
|
jp reset_crc
|
||||||
|
|
||||||
|
+ call print_crc
|
||||||
|
jp test_failed
|
||||||
|
|
||||||
|
|
||||||
|
; Updates checksum with bytes from addr to addr+size-1
|
||||||
|
.macro checksum_mem ARGS addr,size
|
||||||
|
ld hl,addr
|
||||||
|
ld bc,size
|
||||||
|
call checksum_mem_
|
||||||
|
.endm
|
||||||
|
|
||||||
|
checksum_mem_:
|
||||||
|
- ldi a,(hl)
|
||||||
|
call update_crc
|
||||||
|
dec bc
|
||||||
|
ld a,b
|
||||||
|
or c
|
||||||
|
jr nz,-
|
||||||
|
ret
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
[objects]
|
||||||
|
test.o
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
.incdir "common"
|
||||||
|
|
||||||
|
; GBS music file
|
||||||
|
.ifdef BUILD_GBS
|
||||||
|
.include "build_gbs.s"
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; Devcart
|
||||||
|
.ifdef BUILD_DEVCART
|
||||||
|
.include "build_devcart.s"
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; Sub-test in a multi-test ROM
|
||||||
|
.ifdef BUILD_MULTI
|
||||||
|
.include "build_multi.s"
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; GB ROM (default)
|
||||||
|
.ifndef RUNTIME_INCLUDED
|
||||||
|
.include "build_rom.s"
|
||||||
|
.endif
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,86 @@
|
||||||
|
Game Boy Sound Hardware Tests
|
||||||
|
-----------------------------
|
||||||
|
These tests verify aspects of the sound hardware that the CPU can
|
||||||
|
observe. The ROMs and GBSs are either for DMG or CGB hardware, as there
|
||||||
|
are several differences.
|
||||||
|
|
||||||
|
|
||||||
|
Multi-ROM
|
||||||
|
---------
|
||||||
|
In the main directory is a single ROM/GBS which runs all the tests. It
|
||||||
|
prints a test's number, runs the test, then "ok" if it passes, otherwise
|
||||||
|
a failure code. Once all tests have completed it either reports that all
|
||||||
|
tests passed, or reports the number of the first failed test as the
|
||||||
|
result code (1 = first). Finally, it makes several beeps. If a test
|
||||||
|
fails, it can be run on its own by finding the corresponding ROM/GBS in
|
||||||
|
the singles directories.
|
||||||
|
|
||||||
|
Ths compact format on screen is to avoid having the results scroll off
|
||||||
|
the top, so the test can be started and allowed to run without having to
|
||||||
|
constantly monitor the display.
|
||||||
|
|
||||||
|
|
||||||
|
Failure information
|
||||||
|
-------------------
|
||||||
|
For more information about a failure code or information printed, see
|
||||||
|
the test's source code in source/. To find failure code N, search for
|
||||||
|
"set_test N", which will usually be before the subtest which failed.
|
||||||
|
|
||||||
|
|
||||||
|
Flashes, clicks, other glitches
|
||||||
|
-------------------------------
|
||||||
|
Some tests might need to turn the screen off and on, or cause slight
|
||||||
|
audio clicks. This does not indicate failure, and should be ignored.
|
||||||
|
Only the test result reported at the end is important, unless stated
|
||||||
|
otherwise.
|
||||||
|
|
||||||
|
|
||||||
|
LCD support
|
||||||
|
-----------
|
||||||
|
Tests generally print information on screen. The tests will work fine if
|
||||||
|
run on an emulator with NO LCD support, or as an GBS which has no
|
||||||
|
inherent screen; in particular, the VBL wait routine has a timeout in
|
||||||
|
case LY doesn't reflect the current LCD line. The text printing will
|
||||||
|
also work if the LCD doesn't support scrolling.
|
||||||
|
|
||||||
|
|
||||||
|
Output to memory
|
||||||
|
----------------
|
||||||
|
Text output and the final result are also written to memory at $A000,
|
||||||
|
allowing testing a very minimal emulator that supports little more than
|
||||||
|
CPU and RAM. To reliably indicate that the data is from a test and not
|
||||||
|
random data, $A001-$A003 are written with a signature: $DE,$B0,$61. If
|
||||||
|
this is present, then the text string and final result status are valid.
|
||||||
|
|
||||||
|
$A000 holds the overall status. If the test is still running, it holds
|
||||||
|
$80, otherwise it holds the final result code.
|
||||||
|
|
||||||
|
All text output is appended to a zero-terminated string at $A004. An
|
||||||
|
emulator could regularly check this string for any additional
|
||||||
|
characters, and output them, allowing real-time text output, rather than
|
||||||
|
just printing the final output at the end.
|
||||||
|
|
||||||
|
|
||||||
|
GBS versions
|
||||||
|
------------
|
||||||
|
Many GBS-based tests require that the GBS player either not interrupt
|
||||||
|
the init routine with the play routine, or if they do, not interrupt the
|
||||||
|
play routine again if it hasn't returned yet. This is because many tests
|
||||||
|
need to run for a while without returning.
|
||||||
|
|
||||||
|
In addition to the other text output methods described above, GBS builds
|
||||||
|
report essential information bytes audibly, including the final result.
|
||||||
|
A byte is reported as a series of tones. The code is in binary, with a
|
||||||
|
low tone for 0 and a high tone for 1. The first tone is always a zero. A
|
||||||
|
final code of 0 means passed, 1 means failure, and 2 or higher indicates
|
||||||
|
a specific reason as listed in the source code by the corresponding
|
||||||
|
set_code line. Examples:
|
||||||
|
|
||||||
|
Tones Binary Decimal Meaning
|
||||||
|
- - - - - - - - - - - - - - - - - - - -
|
||||||
|
low 0 0 passed
|
||||||
|
low high 01 1 failed
|
||||||
|
low high low 010 2 error 2
|
||||||
|
|
||||||
|
--
|
||||||
|
Shay Green <gblargg@gmail.com>
|
||||||
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue